Compare commits
3 Commits
codex/migr
...
5a80653917
| Author | SHA1 | Date | |
|---|---|---|---|
| 5a80653917 | |||
| bfe1b346d9 | |||
| ef40675422 |
11
.gitignore
vendored
11
.gitignore
vendored
@@ -38,7 +38,6 @@ nbdist/
|
|||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
# Others
|
# Others
|
||||||
.DS_Store
|
|
||||||
*.log
|
*.log
|
||||||
*.xml.versionsBackup
|
*.xml.versionsBackup
|
||||||
*.swp
|
*.swp
|
||||||
@@ -46,3 +45,13 @@ nbdist/
|
|||||||
!*/build/*.java
|
!*/build/*.java
|
||||||
!*/build/*.html
|
!*/build/*.html
|
||||||
!*/build/*.xml
|
!*/build/*.xml
|
||||||
|
|
||||||
|
|
||||||
|
logs/
|
||||||
|
ruoyi-ui/dist.zip
|
||||||
|
*/src/test/
|
||||||
|
ruoyi-ui/tests
|
||||||
|
.playwright-cli
|
||||||
|
|
||||||
|
tongweb_63310.properties
|
||||||
|
audit.log
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
- generic [ref=e2]:
|
|
||||||
- generic [ref=e3]:
|
|
||||||
- generic [ref=e4]:
|
|
||||||
- heading "上虞利率定价系统" [level=3] [ref=e5]
|
|
||||||
- generic [ref=e8]:
|
|
||||||
- textbox "账号" [ref=e9]
|
|
||||||
- img [ref=e11]
|
|
||||||
- generic [ref=e15]:
|
|
||||||
- textbox "密码" [ref=e16]
|
|
||||||
- img [ref=e18]
|
|
||||||
- generic [ref=e20] [cursor=pointer]:
|
|
||||||
- generic [ref=e21]:
|
|
||||||
- checkbox "记住密码"
|
|
||||||
- generic [ref=e23]: 记住密码
|
|
||||||
- button "登 录" [ref=e26] [cursor=pointer]:
|
|
||||||
- generic [ref=e27]: 登 录
|
|
||||||
- generic [ref=e28]: Copyright © 2018-2026 RuoYi. All Rights Reserved.
|
|
||||||
- text:
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
- generic [ref=e2]:
|
|
||||||
- generic [ref=e3]:
|
|
||||||
- generic [ref=e4]:
|
|
||||||
- heading "上虞利率定价系统" [level=3] [ref=e5]
|
|
||||||
- generic [ref=e8]:
|
|
||||||
- textbox "账号" [ref=e9]: admin123admin
|
|
||||||
- img [ref=e11]
|
|
||||||
- generic [ref=e14]:
|
|
||||||
- generic [ref=e15]:
|
|
||||||
- textbox "密码" [ref=e16]
|
|
||||||
- img [ref=e18]
|
|
||||||
- generic [ref=e29]: 请输入您的密码
|
|
||||||
- generic [ref=e20] [cursor=pointer]:
|
|
||||||
- generic [ref=e21]:
|
|
||||||
- checkbox "记住密码"
|
|
||||||
- generic [ref=e23]: 记住密码
|
|
||||||
- button "登 录" [active] [ref=e26] [cursor=pointer]:
|
|
||||||
- generic [ref=e27]: 登 录
|
|
||||||
- generic [ref=e28]: Copyright © 2018-2026 RuoYi. All Rights Reserved.
|
|
||||||
- text:
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
- generic [ref=e2]:
|
|
||||||
@@ -1,191 +0,0 @@
|
|||||||
- generic [ref=e2]:
|
|
||||||
- generic [ref=e3]:
|
|
||||||
- generic [ref=e4]:
|
|
||||||
- link "上虞利率定价系统" [ref=e6] [cursor=pointer]:
|
|
||||||
- /url: /
|
|
||||||
- img [ref=e7]
|
|
||||||
- heading "上虞利率定价系统" [level=1] [ref=e8]
|
|
||||||
- menubar [ref=e12]:
|
|
||||||
- link "流程列表" [ref=e14] [cursor=pointer]:
|
|
||||||
- /url: /index
|
|
||||||
- menuitem "流程列表" [ref=e15]:
|
|
||||||
- img [ref=e16]
|
|
||||||
- text: 流程列表
|
|
||||||
- menuitem "系统管理 " [ref=e19]:
|
|
||||||
- generic [ref=e20] [cursor=pointer]:
|
|
||||||
- img [ref=e21]
|
|
||||||
- text: 系统管理
|
|
||||||
- generic [ref=e23]:
|
|
||||||
- text:
|
|
||||||
- generic [ref=e25]:
|
|
||||||
- generic [ref=e26]:
|
|
||||||
- generic [ref=e27]:
|
|
||||||
- img [ref=e29] [cursor=pointer]
|
|
||||||
- navigation "Breadcrumb" [ref=e31]:
|
|
||||||
- generic:
|
|
||||||
- generic [ref=e32]:
|
|
||||||
- link "首页" [ref=e33]
|
|
||||||
- text: /
|
|
||||||
- generic [ref=e379]:
|
|
||||||
- link "利率定价管理" [ref=e380]
|
|
||||||
- text: /
|
|
||||||
- link "流程列表" [ref=e382]
|
|
||||||
- generic [ref=e36]:
|
|
||||||
- img [ref=e38] [cursor=pointer]
|
|
||||||
- img [ref=e41] [cursor=pointer]
|
|
||||||
- button [ref=e44] [cursor=pointer]:
|
|
||||||
- img [ref=e45]
|
|
||||||
- button "若依" [ref=e48] [cursor=pointer]:
|
|
||||||
- img [ref=e49]
|
|
||||||
- text: 若依
|
|
||||||
- generic [ref=e50]:
|
|
||||||
- generic [ref=e53]:
|
|
||||||
- generic [ref=e54] [cursor=pointer]: 流程列表
|
|
||||||
- generic [ref=e383] [cursor=pointer]:
|
|
||||||
- text: 流程详情
|
|
||||||
- generic [ref=e384]:
|
|
||||||
- text:
|
|
||||||
- generic [ref=e385]:
|
|
||||||
- generic [ref=e386]:
|
|
||||||
- heading "流程详情" [level=2] [ref=e387]
|
|
||||||
- button " 返回" [ref=e388] [cursor=pointer]:
|
|
||||||
- generic [ref=e389]:
|
|
||||||
- text: 返回
|
|
||||||
- generic [ref=e391]:
|
|
||||||
- generic [ref=e393]:
|
|
||||||
- generic [ref=e396]: 关键信息
|
|
||||||
- table [ref=e400]:
|
|
||||||
- rowgroup [ref=e401]:
|
|
||||||
- row "业务方流水号" [ref=e402]:
|
|
||||||
- columnheader "业务方流水号" [ref=e403]
|
|
||||||
- row "20260410150311114" [ref=e404]:
|
|
||||||
- cell "20260410150311114" [ref=e405]
|
|
||||||
- rowgroup [ref=e406]:
|
|
||||||
- row "客户名称" [ref=e407]:
|
|
||||||
- columnheader "客户名称" [ref=e408]
|
|
||||||
- row "t***" [ref=e409]:
|
|
||||||
- cell "t***" [ref=e410]
|
|
||||||
- rowgroup [ref=e411]:
|
|
||||||
- row "客户类型" [ref=e412]:
|
|
||||||
- columnheader "客户类型" [ref=e413]
|
|
||||||
- row "个人" [ref=e414]:
|
|
||||||
- cell "个人" [ref=e415]
|
|
||||||
- rowgroup [ref=e416]:
|
|
||||||
- row "申请金额" [ref=e417]:
|
|
||||||
- columnheader "申请金额" [ref=e418]
|
|
||||||
- row "1000 元" [ref=e419]:
|
|
||||||
- cell "1000 元" [ref=e420]
|
|
||||||
- rowgroup [ref=e421]:
|
|
||||||
- row "基准利率" [ref=e422]:
|
|
||||||
- columnheader "基准利率" [ref=e423]
|
|
||||||
- row "4.35 %" [ref=e424]:
|
|
||||||
- cell "4.35 %" [ref=e425]
|
|
||||||
- rowgroup [ref=e426]:
|
|
||||||
- row "浮动BP" [ref=e427]:
|
|
||||||
- columnheader "浮动BP" [ref=e428]
|
|
||||||
- row "350" [ref=e429]:
|
|
||||||
- cell "350" [ref=e430]
|
|
||||||
- rowgroup [ref=e431]:
|
|
||||||
- row "最终测算利率" [ref=e432]:
|
|
||||||
- columnheader "最终测算利率" [ref=e433]
|
|
||||||
- row "6.05 %" [ref=e434]:
|
|
||||||
- cell "6.05 %" [ref=e435]
|
|
||||||
- rowgroup [ref=e436]:
|
|
||||||
- row "执行利率" [ref=e437]:
|
|
||||||
- columnheader "执行利率" [ref=e438]
|
|
||||||
- row "% 确定" [ref=e439]:
|
|
||||||
- cell "% 确定" [ref=e440]:
|
|
||||||
- generic [ref=e441]:
|
|
||||||
- generic [ref=e442]:
|
|
||||||
- textbox "请输入执行利率" [ref=e443]
|
|
||||||
- generic [ref=e444]: "%"
|
|
||||||
- button "确定" [ref=e445] [cursor=pointer]
|
|
||||||
- generic [ref=e446]:
|
|
||||||
- generic [ref=e447]:
|
|
||||||
- generic [ref=e450]: 流程详情
|
|
||||||
- generic [ref=e451]:
|
|
||||||
- generic [ref=e452]:
|
|
||||||
- heading "基本信息" [level=4] [ref=e453]
|
|
||||||
- table [ref=e456]:
|
|
||||||
- rowgroup [ref=e457]:
|
|
||||||
- row "机构编码 892000 运行模式 1" [ref=e458]:
|
|
||||||
- rowheader "机构编码" [ref=e459]
|
|
||||||
- cell "892000" [ref=e460]
|
|
||||||
- rowheader "运行模式" [ref=e461]
|
|
||||||
- cell "1" [ref=e462]
|
|
||||||
- rowgroup [ref=e463]:
|
|
||||||
- row "客户内码 test 证件类型 身份证" [ref=e464]:
|
|
||||||
- rowheader "客户内码" [ref=e465]
|
|
||||||
- cell "test" [ref=e466]
|
|
||||||
- rowheader "证件类型" [ref=e467]
|
|
||||||
- cell "身份证" [ref=e468]
|
|
||||||
- rowgroup [ref=e469]:
|
|
||||||
- row "证件号码 ** 创建时间 2026-04-10 15:03:11" [ref=e470]:
|
|
||||||
- rowheader "证件号码" [ref=e471]
|
|
||||||
- cell "**" [ref=e472]
|
|
||||||
- rowheader "创建时间" [ref=e473]
|
|
||||||
- cell "2026-04-10 15:03:11" [ref=e474]
|
|
||||||
- rowgroup [ref=e475]:
|
|
||||||
- row "创建者 若依-admin" [ref=e476]:
|
|
||||||
- rowheader "创建者" [ref=e477]
|
|
||||||
- cell "若依-admin" [ref=e478]
|
|
||||||
- generic [ref=e479]:
|
|
||||||
- heading "业务信息" [level=4] [ref=e480]
|
|
||||||
- table [ref=e483]:
|
|
||||||
- rowgroup [ref=e484]:
|
|
||||||
- row "担保方式 信用 申请金额 1000 元" [ref=e485]:
|
|
||||||
- rowheader "担保方式" [ref=e486]
|
|
||||||
- cell "信用" [ref=e487]
|
|
||||||
- rowheader "申请金额" [ref=e488]
|
|
||||||
- cell "1000 元" [ref=e489]
|
|
||||||
- rowgroup [ref=e490]:
|
|
||||||
- row "贷款用途 消费 借款期限 1" [ref=e491]:
|
|
||||||
- rowheader "贷款用途" [ref=e492]
|
|
||||||
- cell "消费" [ref=e493]
|
|
||||||
- rowheader "借款期限" [ref=e494]
|
|
||||||
- cell "1" [ref=e495]
|
|
||||||
- rowgroup [ref=e496]:
|
|
||||||
- row "是否有经营佐证 否 循环功能 否" [ref=e497]:
|
|
||||||
- rowheader "是否有经营佐证" [ref=e498]
|
|
||||||
- cell "否" [ref=e499]
|
|
||||||
- rowheader "循环功能" [ref=e500]
|
|
||||||
- cell "否" [ref=e501]
|
|
||||||
- rowgroup [ref=e502]:
|
|
||||||
- row "抵质押类型 - 抵质押物是否三方所有 否" [ref=e503]:
|
|
||||||
- rowheader "抵质押类型" [ref=e504]
|
|
||||||
- cell "-" [ref=e505]
|
|
||||||
- rowheader "抵质押物是否三方所有" [ref=e506]
|
|
||||||
- cell "否" [ref=e507]
|
|
||||||
- generic [ref=e508]:
|
|
||||||
- generic [ref=e511]: 模型输出
|
|
||||||
- generic [ref=e513]:
|
|
||||||
- generic [ref=e515]:
|
|
||||||
- generic [ref=e517] [cursor=pointer]:
|
|
||||||
- generic [ref=e519] [cursor=pointer]:
|
|
||||||
- tablist [ref=e521]:
|
|
||||||
- tab "基本信息" [selected] [ref=e523]
|
|
||||||
- tab "忠诚度分析" [ref=e524]
|
|
||||||
- tab "贡献度分析" [ref=e525]
|
|
||||||
- tab "关联度分析" [ref=e526]
|
|
||||||
- tab "贷款特征" [ref=e527]
|
|
||||||
- tab "风险度分析" [ref=e528]
|
|
||||||
- tab "测算结果" [ref=e529]
|
|
||||||
- tabpanel "基本信息" [ref=e531]:
|
|
||||||
- table [ref=e534]:
|
|
||||||
- rowgroup [ref=e535]:
|
|
||||||
- row "客户内码 CUST20260121001 客户名称 张*" [ref=e536]:
|
|
||||||
- rowheader "客户内码" [ref=e537]
|
|
||||||
- cell "CUST20260121001" [ref=e538]
|
|
||||||
- rowheader "客户名称" [ref=e539]
|
|
||||||
- cell "张*" [ref=e540]
|
|
||||||
- rowgroup [ref=e541]:
|
|
||||||
- row "证件类型 身份证 证件号码 3301********1234" [ref=e542]:
|
|
||||||
- rowheader "证件类型" [ref=e543]
|
|
||||||
- cell "身份证" [ref=e544]
|
|
||||||
- rowheader "证件号码" [ref=e545]
|
|
||||||
- cell "3301********1234" [ref=e546]
|
|
||||||
- rowgroup [ref=e547]:
|
|
||||||
- row "基准利率 4.35 %" [ref=e548]:
|
|
||||||
- rowheader "基准利率" [ref=e549]
|
|
||||||
- cell "4.35 %" [ref=e550]
|
|
||||||
- text:
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
- generic [ref=e2]:
|
|
||||||
- generic [ref=e3]:
|
|
||||||
- generic [ref=e4]:
|
|
||||||
- heading "上虞利率定价系统" [level=3] [ref=e5]
|
|
||||||
- generic [ref=e8]:
|
|
||||||
- textbox "账号" [ref=e9]
|
|
||||||
- img [ref=e11]
|
|
||||||
- generic [ref=e15]:
|
|
||||||
- textbox "密码" [ref=e16]
|
|
||||||
- img [ref=e18]
|
|
||||||
- generic [ref=e20] [cursor=pointer]:
|
|
||||||
- generic [ref=e21]:
|
|
||||||
- checkbox "记住密码"
|
|
||||||
- generic [ref=e23]: 记住密码
|
|
||||||
- button "登 录" [ref=e26] [cursor=pointer]:
|
|
||||||
- generic [ref=e27]: 登 录
|
|
||||||
- generic [ref=e28]: Copyright © 2018-2026 RuoYi. All Rights Reserved.
|
|
||||||
- text:
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
- generic [ref=e2]:
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
- generic [ref=e2]:
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
- generic [ref=e2]:
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
- generic [active] [ref=e1]:
|
|
||||||
- generic [ref=e2]:
|
|
||||||
- generic [ref=e3]:
|
|
||||||
- generic [ref=e4]:
|
|
||||||
- heading "若依管理系统" [level=3] [ref=e5]
|
|
||||||
- generic [ref=e8]:
|
|
||||||
- textbox "账号" [ref=e9]: admin
|
|
||||||
- img [ref=e11]
|
|
||||||
- generic [ref=e15]:
|
|
||||||
- textbox "密码" [ref=e16]: admin123
|
|
||||||
- img [ref=e18]
|
|
||||||
- generic [ref=e21]:
|
|
||||||
- generic [ref=e22]:
|
|
||||||
- textbox "验证码" [ref=e23]
|
|
||||||
- img [ref=e25]
|
|
||||||
- generic [ref=e27]:
|
|
||||||
- img
|
|
||||||
- generic [ref=e28] [cursor=pointer]:
|
|
||||||
- generic [ref=e29]:
|
|
||||||
- checkbox "记住密码"
|
|
||||||
- generic [ref=e31]: 记住密码
|
|
||||||
- button "登 录" [ref=e34] [cursor=pointer]:
|
|
||||||
- generic [ref=e35]: 登 录
|
|
||||||
- generic [ref=e36]: Copyright © 2018-2026 RuoYi. All Rights Reserved.
|
|
||||||
- text:
|
|
||||||
- alert [ref=e37]:
|
|
||||||
- generic [ref=e38]:
|
|
||||||
- paragraph [ref=e39]: 系统接口500异常
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
- generic [ref=e2]:
|
|
||||||
- generic [ref=e3]:
|
|
||||||
- generic [ref=e4]:
|
|
||||||
- heading "若依管理系统" [level=3] [ref=e5]
|
|
||||||
- generic [ref=e8]:
|
|
||||||
- textbox "账号" [ref=e9]: admin
|
|
||||||
- img [ref=e11]
|
|
||||||
- generic [ref=e15]:
|
|
||||||
- textbox "密码" [ref=e16]: admin123
|
|
||||||
- img [ref=e18]
|
|
||||||
- generic [ref=e20] [cursor=pointer]:
|
|
||||||
- generic [ref=e21]:
|
|
||||||
- checkbox "记住密码"
|
|
||||||
- generic [ref=e23]: 记住密码
|
|
||||||
- button "登 录" [ref=e26] [cursor=pointer]:
|
|
||||||
- generic [ref=e27]: 登 录
|
|
||||||
- generic [ref=e28]: Copyright © 2018-2026 RuoYi. All Rights Reserved.
|
|
||||||
- text:
|
|
||||||
33
README.md
33
README.md
@@ -1,11 +1,11 @@
|
|||||||
<p align="center">
|
<p align="center">
|
||||||
<img alt="logo" src="https://oscimg.oschina.net/oscnet/up-d3d0a9303e11d522a06cd263f3079027715.png">
|
<img alt="logo" src="https://oscimg.oschina.net/oscnet/up-d3d0a9303e11d522a06cd263f3079027715.png">
|
||||||
</p>
|
</p>
|
||||||
<h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">RuoYi v3.9.2</h1>
|
<h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">RuoYi v3.9.1</h1>
|
||||||
<h4 align="center">基于SpringBoot+Vue前后端分离的Java快速开发框架</h4>
|
<h4 align="center">基于SpringBoot+Vue前后端分离的Java快速开发框架</h4>
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://gitee.com/y_project/RuoYi-Vue/stargazers"><img src="https://gitee.com/y_project/RuoYi-Vue/badge/star.svg?theme=dark"></a>
|
<a href="https://gitee.com/y_project/RuoYi-Vue/stargazers"><img src="https://gitee.com/y_project/RuoYi-Vue/badge/star.svg?theme=dark"></a>
|
||||||
<a href="https://gitee.com/y_project/RuoYi-Vue"><img src="https://img.shields.io/badge/RuoYi-v3.9.2-brightgreen.svg"></a>
|
<a href="https://gitee.com/y_project/RuoYi-Vue"><img src="https://img.shields.io/badge/RuoYi-v3.9.1-brightgreen.svg"></a>
|
||||||
<a href="https://gitee.com/y_project/RuoYi-Vue/blob/master/LICENSE"><img src="https://img.shields.io/github/license/mashape/apistatus.svg"></a>
|
<a href="https://gitee.com/y_project/RuoYi-Vue/blob/master/LICENSE"><img src="https://img.shields.io/github/license/mashape/apistatus.svg"></a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
@@ -13,37 +13,16 @@
|
|||||||
|
|
||||||
若依是一套全部开源的快速开发平台,毫无保留给个人及企业免费使用。
|
若依是一套全部开源的快速开发平台,毫无保留给个人及企业免费使用。
|
||||||
|
|
||||||
* 本仓库为RuoYi-Vue的Spring Boot 2 的版本,保持同步更新。
|
|
||||||
* 前端采用Vue、Element UI。
|
* 前端采用Vue、Element UI。
|
||||||
* 后端采用Spring Boot、Spring Security、Redis & Jwt。
|
* 后端采用Spring Boot、Spring Security、Redis & Jwt。
|
||||||
* 权限认证使用Jwt,支持多终端认证系统。
|
* 权限认证使用Jwt,支持多终端认证系统。
|
||||||
* 支持加载动态权限菜单,多方式轻松权限控制。
|
* 支持加载动态权限菜单,多方式轻松权限控制。
|
||||||
* 高效率开发,使用代码生成器可以一键生成前后端代码。
|
* 高效率开发,使用代码生成器可以一键生成前后端代码。
|
||||||
|
* 提供了技术栈([Vue3](https://v3.cn.vuejs.org) [Element Plus](https://element-plus.org/zh-CN) [Vite](https://cn.vitejs.dev))版本[RuoYi-Vue3](https://gitcode.com/yangzongzhuan/RuoYi-Vue3),保持同步更新。
|
||||||
|
* 提供了单应用版本[RuoYi-Vue-fast](https://gitcode.com/yangzongzhuan/RuoYi-Vue-fast),Oracle版本[RuoYi-Vue-Oracle](https://gitcode.com/yangzongzhuan/RuoYi-Vue-Oracle),保持同步更新。
|
||||||
|
* 不分离版本,请移步[RuoYi](https://gitee.com/y_project/RuoYi),微服务版本,请移步[RuoYi-Cloud](https://gitee.com/y_project/RuoYi-Cloud)
|
||||||
* 阿里云折扣场:[点我进入](http://aly.ruoyi.vip),腾讯云秒杀场:[点我进入](http://txy.ruoyi.vip)
|
* 阿里云折扣场:[点我进入](http://aly.ruoyi.vip),腾讯云秒杀场:[点我进入](http://txy.ruoyi.vip)
|
||||||
|
|
||||||
# 版本分支
|
|
||||||
|
|
||||||
RuoYi-Vue 后端项目提供 Spring Boot 2.x / 3.x / 4.x 多版本分支的并行维护。
|
|
||||||
|
|
||||||
| 名称 | 说明 | 地址 |
|
|
||||||
| :---------------- | :------------------------ | :------------------------------------------------------ |
|
|
||||||
| master 默认分支 | Spring Boot 4.x (JDK 17+) | https://gitee.com/y_project/RuoYi-Vue |
|
|
||||||
| springboot3 分支 | Spring Boot 3.x (JDK 17+) | https://gitee.com/y_project/RuoYi-Vue/tree/springboot3 |
|
|
||||||
| springboot2 分支 | Spring Boot 2.x (JDK 8+) | https://gitee.com/y_project/RuoYi-Vue/tree/springboot2 |
|
|
||||||
|
|
||||||
RuoYi-Vue 前端项目提供 Vue 2.x / 3.x / JavaScript TypeScript 版本均可混用搭配
|
|
||||||
|
|
||||||
| 项目名称 | **RuoYi-Vue** | **RuoYi-Vue3** | **RuoYi-Vue3-TypeScript** |
|
|
||||||
| :--- | :--- | :--- | :--- |
|
|
||||||
| **前端框架** | Vue 2 | Vue 3 | Vue 3 |
|
|
||||||
| **脚本语言** | JavaScript | JavaScript | TypeScript |
|
|
||||||
| **构建工具** | Vue CLI | Vite | Vite |
|
|
||||||
| **UI 组件库** | Element UI | Element Plus | Element Plus |
|
|
||||||
| **状态管理** | Vuex | Pinia | Pinia |
|
|
||||||
| **路由管理** | Vue Router 3 | Vue Router 4 | Vue Router 4 |
|
|
||||||
| **核心特点** | 1. 技术栈经典稳定<br>2. 社区资料丰富<br>3. 当前维护重心已转移 | 1. 现代前端技术栈<br>2. 开发体验与性能更优<br>3. 官方主推的活跃版本 | 1. 类型加持,减少沟通成本<br>2. 开发时有提示,效率更高<br>3. 多人协作企业级开发项目 |
|
|
||||||
| **仓库地址** | [RuoYi-Vue](https://gitee.com/y_project/RuoYi-Vue) | [RuoYi-Vue3](https://gitcode.com/yangzongzhuan/RuoYi-Vue3) | [RuoYi-Vue3-TypeScript](https://gitcode.com/yangzongzhuan/RuoYi-Vue3/tree/typescript) |
|
|
||||||
|
|
||||||
## 内置功能
|
## 内置功能
|
||||||
|
|
||||||
1. 用户管理:用户是系统操作者,该功能主要完成系统用户配置。
|
1. 用户管理:用户是系统操作者,该功能主要完成系统用户配置。
|
||||||
@@ -113,4 +92,4 @@ RuoYi-Vue 前端项目提供 Vue 2.x / 3.x / JavaScript TypeScript 版本均可
|
|||||||
|
|
||||||
## 若依前后端分离交流群
|
## 若依前后端分离交流群
|
||||||
|
|
||||||
QQ群: [](https://jq.qq.com/?_wv=1027&k=5bVB1og) [](https://jq.qq.com/?_wv=1027&k=5eiA4DH) [](https://jq.qq.com/?_wv=1027&k=5AxMKlC) [](https://jq.qq.com/?_wv=1027&k=51G72yr) [](https://jq.qq.com/?_wv=1027&k=VvjN2nvu) [](https://jq.qq.com/?_wv=1027&k=5vYAqA05) [](https://jq.qq.com/?_wv=1027&k=kOIINEb5) [](https://jq.qq.com/?_wv=1027&k=UKtX5jhs) [](https://jq.qq.com/?_wv=1027&k=EI9an8lJ) [](https://jq.qq.com/?_wv=1027&k=SWCtLnMz) [](https://jq.qq.com/?_wv=1027&k=96Dkdq0k) [](https://jq.qq.com/?_wv=1027&k=0fsNiYZt) [](https://jq.qq.com/?_wv=1027&k=7xw4xUG1) [](https://jq.qq.com/?_wv=1027&k=eCx8eyoJ) [](https://jq.qq.com/?_wv=1027&k=SpyH2875) [](https://jq.qq.com/?_wv=1027&k=tKEt51dz) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=0vBbSb0ztbBgVtn3kJS-Q4HUNYwip89G&authKey=8irq5PhutrZmWIvsUsklBxhj57l%2F1nOZqjzigkXZVoZE451GG4JHPOqW7AW6cf0T&noverify=0&group_code=143961921) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=ZFAPAbp09S2ltvwrJzp7wGlbopsc0rwi&authKey=HB2cxpxP2yspk%2Bo3WKTBfktRCccVkU26cgi5B16u0KcAYrVu7sBaE7XSEqmMdFQp&noverify=0&group_code=174951577) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=Fn2aF5IHpwsy8j6VlalNJK6qbwFLFHat&authKey=uyIT%2B97x2AXj3odyXpsSpVaPMC%2Bidw0LxG5MAtEqlrcBcWJUA%2FeS43rsF1Tg7IRJ&noverify=0&group_code=161281055) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=XIzkm_mV2xTsUtFxo63bmicYoDBA6Ifm&authKey=dDW%2F4qsmw3x9govoZY9w%2FoWAoC4wbHqGal%2BbqLzoS6VBarU8EBptIgPKN%2FviyC8j&noverify=0&group_code=138988063) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=DkugnCg68PevlycJSKSwjhFqfIgrWWwR&authKey=pR1Pa5lPIeGF%2FFtIk6d%2FGB5qFi0EdvyErtpQXULzo03zbhopBHLWcuqdpwY241R%2F&noverify=0&group_code=151450850) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=F58bgRa-Dp-rsQJThiJqIYv8t4-lWfXh&authKey=UmUs4CVG5OPA1whvsa4uSespOvyd8%2FAr9olEGaWAfdLmfKQk%2FVBp2YU3u2xXXt76&noverify=0&group_code=224622315) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=Nxb2EQ5qozWa218Wbs7zgBnjLSNk_tVT&authKey=obBKXj6SBKgrFTJZx0AqQnIYbNOvBB2kmgwWvGhzxR67RoRr84%2Bus5OadzMcdJl5&noverify=0&group_code=287842588) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=numtK1M_I4eVd2Gvg8qtbuL8JgX42qNh&authKey=giV9XWMaFZTY%2FqPlmWbkB9g3fi0Ev5CwEtT9Tgei0oUlFFCQLDp4ozWRiVIzubIm&noverify=0&group_code=187944233) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=G6r5KGCaa3pqdbUSXNIgYloyb8e0_L0D&authKey=4w8tF1eGW7%2FedWn%2FHAypQksdrML%2BDHolQSx7094Agm7Luakj9EbfPnSTxSi2T1LQ&noverify=0&group_code=228578329) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=GsOo-OLz53J8y_9TPoO6XXSGNRTgbFxA&authKey=R7Uy%2Feq%2BZsoKNqHvRKhiXpypW7DAogoWapOawUGHokJSBIBIre2%2FoiAZeZBSLuBc&noverify=0&group_code=191164766) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=PmYavuzsOthVqfdAPbo4uAeIbu7Ttjgc&authKey=p52l8%2FXa4PS1JcEmS3VccKSwOPJUZ1ZfQ69MEKzbrooNUljRtlKjvsXf04bxNp3G&noverify=0&group_code=174569686) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=M9y5NjAl44lAL_Vh2crmEehZU_PMU6KS&authKey=ZSDz8hEREWSaPuxQV3gEwqGIaGjfRNnkB4rJjf0IvXhrSUGSGwQFmBA%2Boe8HFxyl&noverify=0&group_code=127358632) 点击按钮入群。
|
QQ群: [](https://jq.qq.com/?_wv=1027&k=5bVB1og) [](https://jq.qq.com/?_wv=1027&k=5eiA4DH) [](https://jq.qq.com/?_wv=1027&k=5AxMKlC) [](https://jq.qq.com/?_wv=1027&k=51G72yr) [](https://jq.qq.com/?_wv=1027&k=VvjN2nvu) [](https://jq.qq.com/?_wv=1027&k=5vYAqA05) [](https://jq.qq.com/?_wv=1027&k=kOIINEb5) [](https://jq.qq.com/?_wv=1027&k=UKtX5jhs) [](https://jq.qq.com/?_wv=1027&k=EI9an8lJ) [](https://jq.qq.com/?_wv=1027&k=SWCtLnMz) [](https://jq.qq.com/?_wv=1027&k=96Dkdq0k) [](https://jq.qq.com/?_wv=1027&k=0fsNiYZt) [](https://jq.qq.com/?_wv=1027&k=7xw4xUG1) [](https://jq.qq.com/?_wv=1027&k=eCx8eyoJ) [](https://jq.qq.com/?_wv=1027&k=SpyH2875) [](https://jq.qq.com/?_wv=1027&k=tKEt51dz) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=0vBbSb0ztbBgVtn3kJS-Q4HUNYwip89G&authKey=8irq5PhutrZmWIvsUsklBxhj57l%2F1nOZqjzigkXZVoZE451GG4JHPOqW7AW6cf0T&noverify=0&group_code=143961921) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=ZFAPAbp09S2ltvwrJzp7wGlbopsc0rwi&authKey=HB2cxpxP2yspk%2Bo3WKTBfktRCccVkU26cgi5B16u0KcAYrVu7sBaE7XSEqmMdFQp&noverify=0&group_code=174951577) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=Fn2aF5IHpwsy8j6VlalNJK6qbwFLFHat&authKey=uyIT%2B97x2AXj3odyXpsSpVaPMC%2Bidw0LxG5MAtEqlrcBcWJUA%2FeS43rsF1Tg7IRJ&noverify=0&group_code=161281055) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=XIzkm_mV2xTsUtFxo63bmicYoDBA6Ifm&authKey=dDW%2F4qsmw3x9govoZY9w%2FoWAoC4wbHqGal%2BbqLzoS6VBarU8EBptIgPKN%2FviyC8j&noverify=0&group_code=138988063) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=DkugnCg68PevlycJSKSwjhFqfIgrWWwR&authKey=pR1Pa5lPIeGF%2FFtIk6d%2FGB5qFi0EdvyErtpQXULzo03zbhopBHLWcuqdpwY241R%2F&noverify=0&group_code=151450850) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=F58bgRa-Dp-rsQJThiJqIYv8t4-lWfXh&authKey=UmUs4CVG5OPA1whvsa4uSespOvyd8%2FAr9olEGaWAfdLmfKQk%2FVBp2YU3u2xXXt76&noverify=0&group_code=224622315) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=Nxb2EQ5qozWa218Wbs7zgBnjLSNk_tVT&authKey=obBKXj6SBKgrFTJZx0AqQnIYbNOvBB2kmgwWvGhzxR67RoRr84%2Bus5OadzMcdJl5&noverify=0&group_code=287842588) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=numtK1M_I4eVd2Gvg8qtbuL8JgX42qNh&authKey=giV9XWMaFZTY%2FqPlmWbkB9g3fi0Ev5CwEtT9Tgei0oUlFFCQLDp4ozWRiVIzubIm&noverify=0&group_code=187944233) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=G6r5KGCaa3pqdbUSXNIgYloyb8e0_L0D&authKey=4w8tF1eGW7%2FedWn%2FHAypQksdrML%2BDHolQSx7094Agm7Luakj9EbfPnSTxSi2T1LQ&noverify=0&group_code=228578329) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=GsOo-OLz53J8y_9TPoO6XXSGNRTgbFxA&authKey=R7Uy%2Feq%2BZsoKNqHvRKhiXpypW7DAogoWapOawUGHokJSBIBIre2%2FoiAZeZBSLuBc&noverify=0&group_code=191164766) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=PmYavuzsOthVqfdAPbo4uAeIbu7Ttjgc&authKey=p52l8%2FXa4PS1JcEmS3VccKSwOPJUZ1ZfQ69MEKzbrooNUljRtlKjvsXf04bxNp3G&noverify=0&group_code=174569686) 点击按钮入群。
|
||||||
BIN
bin/.DS_Store
vendored
Normal file
BIN
bin/.DS_Store
vendored
Normal file
Binary file not shown.
0
bin/prod/restart_java_test.sh
Executable file → Normal file
0
bin/prod/restart_java_test.sh
Executable file → Normal file
0
bin/restart_java_backend_test.sh
Executable file → Normal file
0
bin/restart_java_backend_test.sh
Executable file → Normal file
@@ -1,43 +0,0 @@
|
|||||||
# 本地 Tomcat 与 TongWeb 打包并存后端实施计划
|
|
||||||
|
|
||||||
## 目标
|
|
||||||
|
|
||||||
- 恢复本地 `jar + 内嵌 Tomcat` 启动链路
|
|
||||||
- 保留服务器 `war + TongWeb` 部署链路
|
|
||||||
- 一次 `mvn package` 同时产出 `ruoyi-admin.jar` 和 `ruoyi-admin.war`
|
|
||||||
|
|
||||||
## 改动范围
|
|
||||||
|
|
||||||
- Maven 打包配置
|
|
||||||
- 后端启动与部署脚本
|
|
||||||
- 脚本测试
|
|
||||||
- 相关运行文档和实施记录
|
|
||||||
|
|
||||||
## 实施步骤
|
|
||||||
|
|
||||||
1. 先修改脚本测试,重新定义目标行为
|
|
||||||
- 本地测试脚本期望 `restart_java_backend.sh` 使用 `java -jar`
|
|
||||||
- 生产测试脚本继续期望 TongWeb 使用 `war`
|
|
||||||
2. 调整 Maven 打包配置
|
|
||||||
- `ruoyi-admin` 恢复主产物 `jar`
|
|
||||||
- 增加附加 `war` 产物
|
|
||||||
- 恢复本地运行所需的内嵌 Tomcat 依赖
|
|
||||||
3. 调整脚本
|
|
||||||
- 本地脚本改回管理 `ruoyi-admin.jar`
|
|
||||||
- 生产脚本继续管理 `ruoyi-admin.war`
|
|
||||||
4. 更新文档
|
|
||||||
- 更新运行说明
|
|
||||||
- 新增本次实施记录
|
|
||||||
5. 执行验证
|
|
||||||
|
|
||||||
## 验证要求
|
|
||||||
|
|
||||||
- `sh bin/restart_java_backend_test.sh`
|
|
||||||
- `sh bin/prod/restart_java_test.sh`
|
|
||||||
- `sh bin/prod/deploy_from_package_test.sh`
|
|
||||||
- `sh -n bin/restart_java_backend.sh`
|
|
||||||
- `sh -n bin/prod/restart_java.sh`
|
|
||||||
- `sh -n bin/prod/deploy_from_package.sh`
|
|
||||||
- `mvn -pl ruoyi-admin -am package -DskipTests`
|
|
||||||
- 确认 `ruoyi-admin/target/ruoyi-admin.jar`
|
|
||||||
- 确认 `ruoyi-admin/target/ruoyi-admin.war`
|
|
||||||
@@ -1,147 +0,0 @@
|
|||||||
# 本地 Tomcat 运行与 TongWeb 打包并存设计
|
|
||||||
|
|
||||||
## 背景
|
|
||||||
|
|
||||||
当前项目已经被调整为统一的 TongWeb `war` 交付模式,这会导致本地开发时也必须围绕 TongWeb 组织启动流程,不符合当前开发诉求。
|
|
||||||
|
|
||||||
本次目标是同时保留两条链路:
|
|
||||||
|
|
||||||
- 本地开发运行继续使用内嵌 Tomcat
|
|
||||||
- 打包交付继续支持服务器上的 TongWeb
|
|
||||||
|
|
||||||
并且要求一次 `mvn package` 同时产出本地运行所需的 `jar` 和服务器部署所需的 `war`。
|
|
||||||
|
|
||||||
## 目标
|
|
||||||
|
|
||||||
- 保留 `IDEA`、`mvn spring-boot:run`、本地脚本直启后端的开发体验
|
|
||||||
- 保留面向 TongWeb 的 `war` 交付方式
|
|
||||||
- `mvn package` 后同时得到 `ruoyi-admin.jar` 与 `ruoyi-admin.war`
|
|
||||||
- 本地不强依赖安装 TongWeb
|
|
||||||
- 服务器部署脚本继续只消费 `war`
|
|
||||||
|
|
||||||
## 非目标
|
|
||||||
|
|
||||||
- 不新增第二个后端启动模块
|
|
||||||
- 不拆分额外的部署工程
|
|
||||||
- 不修改前端构建方式
|
|
||||||
- 不引入“兼容模式”“降级模式”之类额外分支逻辑
|
|
||||||
|
|
||||||
## 设计方案
|
|
||||||
|
|
||||||
### 1. 构建产物设计
|
|
||||||
|
|
||||||
`ruoyi-admin` 恢复为以 `jar` 为主产物的 Spring Boot 应用,用于本地开发运行。
|
|
||||||
|
|
||||||
在同一个 Maven 模块中补充 `war` 打包步骤,使一次 `mvn package` 后同时得到:
|
|
||||||
|
|
||||||
- `ruoyi-admin/target/ruoyi-admin.jar`
|
|
||||||
- `ruoyi-admin/target/ruoyi-admin.war`
|
|
||||||
|
|
||||||
这样本地和服务器都从同一套源码构建,但消费不同产物:
|
|
||||||
|
|
||||||
- 本地消费 `jar`
|
|
||||||
- 服务器消费 `war`
|
|
||||||
|
|
||||||
### 2. 依赖设计
|
|
||||||
|
|
||||||
为了保证本地可继续走内嵌 Tomcat:
|
|
||||||
|
|
||||||
- 恢复 Web 模块中的内嵌 Tomcat 依赖链
|
|
||||||
- 保持 `spring-boot:run` 与 `java -jar` 均可正常工作
|
|
||||||
|
|
||||||
为了保证 TongWeb 外部容器部署:
|
|
||||||
|
|
||||||
- 打出的 `war` 不能把容器自身实现错误打包成部署冲突形式
|
|
||||||
- `Servlet API` 继续按外部容器提供的思路处理
|
|
||||||
|
|
||||||
本质上,本地运行和 TongWeb 部署共享同一套业务代码,但运行容器不同。
|
|
||||||
|
|
||||||
### 3. 启动脚本设计
|
|
||||||
|
|
||||||
#### 本地脚本
|
|
||||||
|
|
||||||
`bin/restart_java_backend.sh` 恢复为本地开发脚本:
|
|
||||||
|
|
||||||
- 执行 Maven 打包
|
|
||||||
- 使用 `ruoyi-admin.jar`
|
|
||||||
- 通过 `java -jar` 管理本地后端进程
|
|
||||||
|
|
||||||
这条链路不再依赖 `TONGWEB_HOME`。
|
|
||||||
|
|
||||||
#### 生产脚本
|
|
||||||
|
|
||||||
以下脚本保持 TongWeb 交付模型:
|
|
||||||
|
|
||||||
- `bin/prod/restart_java.sh`
|
|
||||||
- `bin/prod/deploy_from_package.sh`
|
|
||||||
- `bin/prod/deploy_release.sh`
|
|
||||||
|
|
||||||
它们继续只处理 `ruoyi-admin.war`,不回退到 `jar`。
|
|
||||||
|
|
||||||
### 4. 本地与服务器联调设计
|
|
||||||
|
|
||||||
本地开发时不要求本机安装 TongWeb。
|
|
||||||
|
|
||||||
如果需要验证 TongWeb 运行环境,只通过两种方式完成:
|
|
||||||
|
|
||||||
- 打包后部署到服务器 TongWeb 验证
|
|
||||||
- 本地系统直接调用服务器上已部署的 TongWeb 地址联调
|
|
||||||
|
|
||||||
这意味着:
|
|
||||||
|
|
||||||
- 本地开发链路只围绕 `jar + Tomcat`
|
|
||||||
- 服务器部署链路只围绕 `war + TongWeb`
|
|
||||||
|
|
||||||
## 验证方案
|
|
||||||
|
|
||||||
### 构建验证
|
|
||||||
|
|
||||||
执行:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
mvn -pl ruoyi-admin -am package -DskipTests
|
|
||||||
```
|
|
||||||
|
|
||||||
确认同时存在:
|
|
||||||
|
|
||||||
- `ruoyi-admin/target/ruoyi-admin.jar`
|
|
||||||
- `ruoyi-admin/target/ruoyi-admin.war`
|
|
||||||
|
|
||||||
### 本地运行验证
|
|
||||||
|
|
||||||
执行:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
sh bin/restart_java_backend.sh restart
|
|
||||||
```
|
|
||||||
|
|
||||||
确认本地以 `java -jar` 正常运行。
|
|
||||||
|
|
||||||
### TongWeb 脚本验证
|
|
||||||
|
|
||||||
执行:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
sh bin/prod/restart_java_test.sh
|
|
||||||
sh bin/prod/deploy_from_package_test.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
确认 TongWeb 侧仍围绕 `war` 工作。
|
|
||||||
|
|
||||||
## 影响范围
|
|
||||||
|
|
||||||
- `ruoyi-admin` Maven 打包配置
|
|
||||||
- Web 相关模块的容器依赖声明
|
|
||||||
- 本地后端脚本
|
|
||||||
- 生产 TongWeb 脚本
|
|
||||||
- 运行文档与实施记录
|
|
||||||
|
|
||||||
## 结论
|
|
||||||
|
|
||||||
本方案采用最短路径实现“双产物、双运行链路并存”:
|
|
||||||
|
|
||||||
- 本地运行继续走内嵌 Tomcat
|
|
||||||
- 服务器部署继续走 TongWeb
|
|
||||||
- 一次打包同时产出 `jar` 与 `war`
|
|
||||||
|
|
||||||
在不新增模块、不扩散复杂度的前提下,满足开发与部署两端的实际需要。
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
# 东方通替换 Tomcat 后端实施计划
|
|
||||||
|
|
||||||
## 目标
|
|
||||||
|
|
||||||
- 将后端交付形态从内嵌 Tomcat 的 `jar` 调整为部署到东方通 TongWeb 的 `war`
|
|
||||||
- 清理当前发布链路中围绕 `java -jar` / `ruoyi-admin.jar` 的脚本约定
|
|
||||||
- 保持现有前端发布方式和 Nginx 入口不变,后端仍沿用 `63310` 作为反向代理目标端口
|
|
||||||
|
|
||||||
## 改动范围
|
|
||||||
|
|
||||||
- Maven 构建
|
|
||||||
- 调整 `ruoyi-admin` 打包类型为 `war`
|
|
||||||
- 去除模块链路中的嵌入式 Tomcat 打包依赖
|
|
||||||
- 明确 Servlet API 由外部容器提供
|
|
||||||
- 部署脚本
|
|
||||||
- 将生产部署脚本中的后端产物从 `ruoyi-admin.jar` 切换为 `ruoyi-admin.war`
|
|
||||||
- 将生产重启脚本从 Java 进程启停改为 TongWeb 容器启停与 `war` 发布
|
|
||||||
- 调整本地后端重启脚本,使其面向 TongWeb 进行构建和部署
|
|
||||||
- 运行文档
|
|
||||||
- 更新本地安装手册中的后端环境说明,改为 TongWeb
|
|
||||||
- 新增本次改动实施记录
|
|
||||||
|
|
||||||
## 实施步骤
|
|
||||||
|
|
||||||
1. 先修改现有脚本测试,明确新的 `war + TongWeb` 约束
|
|
||||||
2. 调整 Maven 配置,产出 `ruoyi-admin.war`
|
|
||||||
3. 修改生产部署脚本和本地重启脚本
|
|
||||||
4. 更新运行文档与实施记录
|
|
||||||
5. 执行脚本测试、语法校验和 Maven 打包验证
|
|
||||||
|
|
||||||
## 验证要求
|
|
||||||
|
|
||||||
- `mvn -pl ruoyi-admin -am clean package -DskipTests` 成功,且产物为 `ruoyi-admin.war`
|
|
||||||
- `sh bin/prod/restart_java_test.sh` 成功
|
|
||||||
- `sh bin/prod/deploy_from_package_test.sh` 成功
|
|
||||||
- `sh bin/restart_java_backend_test.sh` 成功
|
|
||||||
- `sh -n bin/prod/restart_java.sh`
|
|
||||||
- `sh -n bin/prod/deploy_from_package.sh`
|
|
||||||
- `sh -n bin/restart_java_backend.sh`
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
# RuoYi-Vue springboot2 后端迁移实施计划
|
|
||||||
|
|
||||||
## 目标
|
|
||||||
|
|
||||||
以上游 `RuoYi-Vue/springboot2` 为后端框架基线,将当前项目的后端框架层整体回退并重对齐到 Spring Boot 2 / Java 8,同时恢复 `ruoyi-loan-pricing` 业务模块和管理端业务接入配置。
|
|
||||||
|
|
||||||
## 范围
|
|
||||||
|
|
||||||
- 根 `pom.xml`
|
|
||||||
- `ruoyi-admin`
|
|
||||||
- `ruoyi-common`
|
|
||||||
- `ruoyi-framework`
|
|
||||||
- `ruoyi-generator`
|
|
||||||
- `ruoyi-quartz`
|
|
||||||
- `ruoyi-system`
|
|
||||||
- `ruoyi-loan-pricing`
|
|
||||||
- `sql`
|
|
||||||
|
|
||||||
## 执行步骤
|
|
||||||
|
|
||||||
1. 备份当前后端业务模块与业务配置
|
|
||||||
2. 用上游 `springboot2` 覆盖根 POM 和基础后端模块
|
|
||||||
3. 恢复 `ruoyi-loan-pricing` 模块目录
|
|
||||||
4. 在根 POM 与 `ruoyi-admin/pom.xml` 中重新挂载 `ruoyi-loan-pricing`
|
|
||||||
5. 恢复 `ruoyi-admin/src/main/resources` 中的 `loan-pricing` 业务配置
|
|
||||||
6. 检查并修正 `ruoyi-loan-pricing` 中不兼容 Spring Boot 2 的依赖、注解和包引用
|
|
||||||
7. 校正 Mapper、资源文件和测试依赖,保证模块能参与 Maven 聚合构建
|
|
||||||
8. 保留并整理业务 SQL 脚本
|
|
||||||
9. 在 Java 8 环境下执行后端编译与关键测试
|
|
||||||
|
|
||||||
## 验证要求
|
|
||||||
|
|
||||||
- `mvn -pl ruoyi-admin -am test` 至少能够完成依赖解析和关键模块测试
|
|
||||||
- `mvn -pl ruoyi-admin -am package -DskipTests` 能通过
|
|
||||||
- `ruoyi-loan-pricing` 模块可被 `ruoyi-admin` 正常引用
|
|
||||||
|
|
||||||
## 注意事项
|
|
||||||
|
|
||||||
- 不保留 Spring Boot 3 / Java 17 双配置
|
|
||||||
- 不引入兼容层或过渡层
|
|
||||||
- 若业务模块使用了 Boot 3 专属依赖,直接改为 Boot 2 可运行实现
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
# RuoYi-Vue springboot2 前端迁移实施计划
|
|
||||||
|
|
||||||
## 目标
|
|
||||||
|
|
||||||
以上游 `RuoYi-Vue/springboot2` 为前端基线,将当前项目前端整体回退并重对齐到上游 `ruoyi-ui`,然后恢复 `loanPricing` 业务页面、接口调用、路由与相关依赖。
|
|
||||||
|
|
||||||
## 范围
|
|
||||||
|
|
||||||
- `ruoyi-ui/package.json`
|
|
||||||
- `ruoyi-ui/src`
|
|
||||||
- `ruoyi-ui/public`
|
|
||||||
- `ruoyi-ui/build`
|
|
||||||
- `ruoyi-ui/tests`
|
|
||||||
|
|
||||||
## 执行步骤
|
|
||||||
|
|
||||||
1. 备份当前 `loanPricing` 页面、接口文件、路由改动和业务测试脚本
|
|
||||||
2. 用上游 `springboot2` 的 `ruoyi-ui` 覆盖当前前端框架层
|
|
||||||
3. 恢复 `src/views/loanPricing` 页面目录
|
|
||||||
4. 恢复 `src/api/loanPricing` 接口文件
|
|
||||||
5. 将业务路由重新挂回 `src/router/index.js`
|
|
||||||
6. 恢复业务所需的前端依赖与测试脚本
|
|
||||||
7. 用 `nvm` 切换到合适的 Node 版本后重新安装依赖
|
|
||||||
8. 执行前端构建与页面联调验证
|
|
||||||
|
|
||||||
## 验证要求
|
|
||||||
|
|
||||||
- `npm install` 成功
|
|
||||||
- `npm run build:prod` 成功
|
|
||||||
- `loanPricing` 页面路由可访问
|
|
||||||
- 页面基础交互和接口调用链路未丢失
|
|
||||||
|
|
||||||
## 注意事项
|
|
||||||
|
|
||||||
- 前端直接以 `springboot2` 上游为准,不保留当前非业务性的历史前端定制
|
|
||||||
- Node 版本必须通过 `nvm` 控制
|
|
||||||
- 测试完成后要关闭前端调试进程
|
|
||||||
@@ -1,120 +0,0 @@
|
|||||||
# RuoYi-Vue springboot2 基线迁移设计
|
|
||||||
|
|
||||||
## 1. 目标
|
|
||||||
|
|
||||||
本次迁移以上游 `https://gitee.com/y_project/RuoYi-Vue/tree/springboot2` 为唯一框架基线,先将当前仓库整体回退并重对齐到该基线,再迁回现有业务模块与业务页面,最终形成一个“框架层跟随上游、业务层保留现状”的项目结构。
|
|
||||||
|
|
||||||
本次迁移不采用兼容层、补丁层或双栈并存方案,不保留 Spring Boot 3 / Java 17 的框架实现。
|
|
||||||
|
|
||||||
## 2. 现状与目标差异
|
|
||||||
|
|
||||||
当前仓库已经是 RuoYi 多模块工程,但后端已升级到 `Spring Boot 3.5.x`、`Java 17`,并引入了以下业务定制:
|
|
||||||
|
|
||||||
- 后端业务模块:`ruoyi-loan-pricing`
|
|
||||||
- 前端业务页面:`ruoyi-ui/src/views/loanPricing`
|
|
||||||
- 前端业务接口:`ruoyi-ui/src/api/loanPricing`
|
|
||||||
- 管理端业务接入:`ruoyi-admin` 中的业务依赖与配置
|
|
||||||
- 业务 SQL:`sql/loan_pricing_*`、`sql/model_*`、`sql/loan_pricing_menu.sql`
|
|
||||||
|
|
||||||
目标上游 `springboot2` 分支采用:
|
|
||||||
|
|
||||||
- `RuoYi-Vue 3.9.2`
|
|
||||||
- `Spring Boot 2.5.15`
|
|
||||||
- `Java 8`
|
|
||||||
- `Vue 2 + Element UI`
|
|
||||||
|
|
||||||
因此本次迁移的本质是:先将框架层彻底切回 Spring Boot 2 基线,再把利率定价业务重新挂载到新的基线上。
|
|
||||||
|
|
||||||
## 3. 迁移范围
|
|
||||||
|
|
||||||
### 3.1 框架层
|
|
||||||
|
|
||||||
以下内容以上游 `springboot2` 版本为准:
|
|
||||||
|
|
||||||
- 根目录框架文件与脚本
|
|
||||||
- 根 `pom.xml`
|
|
||||||
- `ruoyi-admin`
|
|
||||||
- `ruoyi-common`
|
|
||||||
- `ruoyi-framework`
|
|
||||||
- `ruoyi-generator`
|
|
||||||
- `ruoyi-quartz`
|
|
||||||
- `ruoyi-system`
|
|
||||||
- `ruoyi-ui`
|
|
||||||
- 上游自带 `sql` 基础脚本
|
|
||||||
|
|
||||||
### 3.2 业务层
|
|
||||||
|
|
||||||
以下内容需要从当前仓库迁回到新基线:
|
|
||||||
|
|
||||||
- `ruoyi-loan-pricing` 全模块
|
|
||||||
- `ruoyi-admin` 中与 `loan-pricing` 相关的业务配置、业务依赖
|
|
||||||
- `ruoyi-ui/src/views/loanPricing` 页面
|
|
||||||
- `ruoyi-ui/src/api/loanPricing` 接口文件
|
|
||||||
- `ruoyi-ui/src/router/index.js` 中的业务路由
|
|
||||||
- 业务 SQL、部署脚本、项目文档
|
|
||||||
|
|
||||||
## 4. 实施策略
|
|
||||||
|
|
||||||
### 4.1 基线覆盖策略
|
|
||||||
|
|
||||||
采用“上游覆盖 + 业务回贴”模式:
|
|
||||||
|
|
||||||
1. 先备份当前业务目录与业务配置
|
|
||||||
2. 将上游 `springboot2` 内容覆盖到当前仓库
|
|
||||||
3. 恢复业务模块、业务页面、业务配置和业务 SQL
|
|
||||||
4. 处理 Spring Boot 2 下的编译和运行差异
|
|
||||||
|
|
||||||
### 4.2 后端回贴策略
|
|
||||||
|
|
||||||
后端只保留一套 Spring Boot 2 实现,不额外保留 Spring Boot 3 兼容写法。若 `ruoyi-loan-pricing` 内存在 Boot 3 / Jakarta / SpringDoc 相关依赖或 API,则直接改回 Boot 2 可运行写法。
|
|
||||||
|
|
||||||
### 4.3 前端回贴策略
|
|
||||||
|
|
||||||
前端以 `springboot2` 上游 `ruoyi-ui` 为基础,回贴 `loanPricing` 页面、接口调用、路由和必要依赖;不保留与当前业务无关的历史定制。
|
|
||||||
|
|
||||||
## 5. 风险点与处理原则
|
|
||||||
|
|
||||||
### 5.1 框架依赖回退风险
|
|
||||||
|
|
||||||
风险:
|
|
||||||
|
|
||||||
- `springdoc`、`jakarta.*`、Boot 3 专用依赖不兼容 Boot 2
|
|
||||||
- 测试依赖、插件版本、JDK 版本需要一并回退
|
|
||||||
|
|
||||||
处理原则:
|
|
||||||
|
|
||||||
- 以 Boot 2 上游依赖为准
|
|
||||||
- 业务模块仅保留完成业务所必需的依赖
|
|
||||||
|
|
||||||
### 5.2 业务接入点遗漏风险
|
|
||||||
|
|
||||||
风险:
|
|
||||||
|
|
||||||
- `ruoyi-admin` 配置遗漏
|
|
||||||
- 前端路由、菜单、接口路径遗漏
|
|
||||||
- SQL 脚本与权限菜单脚本遗漏
|
|
||||||
|
|
||||||
处理原则:
|
|
||||||
|
|
||||||
- 逐类枚举迁移对象
|
|
||||||
- 迁移后通过编译、页面访问、接口调用进行闭环验证
|
|
||||||
|
|
||||||
## 6. 验证标准
|
|
||||||
|
|
||||||
迁移完成后至少满足以下条件:
|
|
||||||
|
|
||||||
- Maven 多模块在 Spring Boot 2 / Java 8 环境下可编译
|
|
||||||
- `ruoyi-admin` 可启动
|
|
||||||
- `ruoyi-ui` 在指定 Node 版本下可安装并构建
|
|
||||||
- `loanPricing` 页面路由可访问
|
|
||||||
- 利率定价相关接口类与 Mapper 可通过编译
|
|
||||||
- 业务 SQL 与菜单脚本仍保留在仓库内
|
|
||||||
|
|
||||||
## 7. 产出物
|
|
||||||
|
|
||||||
本次任务最终需产出:
|
|
||||||
|
|
||||||
- 本设计文档
|
|
||||||
- 后端实施计划文档
|
|
||||||
- 前端实施计划文档
|
|
||||||
- 迁移实施记录文档
|
|
||||||
52
doc/2026-04-16-shangyu-corporate-alignment-backend-plan.md
Normal file
52
doc/2026-04-16-shangyu-corporate-alignment-backend-plan.md
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
# 上虞对公利率测算字段对齐后端实施计划
|
||||||
|
|
||||||
|
## 目标
|
||||||
|
- 对齐对公创建接口、模型调用入参、流程详情返回、mock 返回和 SQL 基线。
|
||||||
|
|
||||||
|
## 实施内容
|
||||||
|
- 创建请求字段改为 Excel `上传指标` 口径:
|
||||||
|
- 新增 `repayMethod`
|
||||||
|
- `isTradeConstruction` 改为 `isTradeBuildEnt`
|
||||||
|
- 移除对公创建链路中的 `isAgriGuar`、`isTechEnt`
|
||||||
|
- 流程主表实体补 `repayMethod`,并将 `isTradeBuildEnt` 映射到数据库列 `is_trade_construction`
|
||||||
|
- 对公模型输出实体补齐:
|
||||||
|
- `repayMethod`
|
||||||
|
- `isTradeBuildEnt`
|
||||||
|
- `loanRateHistory`
|
||||||
|
- `minRateProduct`
|
||||||
|
- `smoothRange`
|
||||||
|
- `finalCalculateRate`
|
||||||
|
- `referenceRate`
|
||||||
|
- 对公模型输出实体不再暴露:
|
||||||
|
- `isAgriGuar`
|
||||||
|
- `midEntTax`
|
||||||
|
- `cardOverdue`
|
||||||
|
- 企业模型入参统一值域:
|
||||||
|
- `isGreenLoan`、`isTradeBuildEnt`、`collThirdParty` 发送 `0/1`
|
||||||
|
- `repayMethod` 发送 `分期/不分期`
|
||||||
|
- 企业流程详情主利率改为 `finalCalculateRate`
|
||||||
|
- mock 继续保留 `data.mappingOutputFields` 包装层,只更新企业字段集合和值域
|
||||||
|
|
||||||
|
## SQL 调整
|
||||||
|
- `loan_pricing_workflow` 新增 `repay_method`
|
||||||
|
- `model_corp_output_fields` 新增:
|
||||||
|
- `repay_method`
|
||||||
|
- `is_trade_build_ent`
|
||||||
|
- `loan_rate_history`
|
||||||
|
- `min_rate_product`
|
||||||
|
- `smooth_range`
|
||||||
|
- `final_calculate_rate`
|
||||||
|
- `reference_rate`
|
||||||
|
- 已同步更新:
|
||||||
|
- `sql/loan_pricing_workflow.sql`
|
||||||
|
- `sql/model_corp.sql`
|
||||||
|
- `sql/loan_pricing_schema_20260328.sql`
|
||||||
|
- `sql/loan_pricing_prod_init_20260331.sql`
|
||||||
|
- `sql/2026-04-16-shangyu-corporate-alignment.sql`
|
||||||
|
|
||||||
|
## 验证
|
||||||
|
- 运行后端定向单测,确认对公字段和详情主利率断言通过
|
||||||
|
- 使用 `/login/test` 获取 token 后调用对公创建和详情接口,确认:
|
||||||
|
- 正常场景成功
|
||||||
|
- 缺少 `repayMethod` 返回校验错误
|
||||||
|
- 详情返回包含新增字段且 `loanRate = finalCalculateRate`
|
||||||
48
doc/2026-04-16-shangyu-corporate-alignment-frontend-plan.md
Normal file
48
doc/2026-04-16-shangyu-corporate-alignment-frontend-plan.md
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
# 上虞对公利率测算字段对齐前端实施计划
|
||||||
|
|
||||||
|
## 目标
|
||||||
|
- 对齐对公新增弹窗和企业流程详情页展示,严格跟随 Excel `上传指标` 与 `展示指标`。
|
||||||
|
|
||||||
|
## 实施内容
|
||||||
|
- 对公新增弹窗调整为 Excel `上传指标`:
|
||||||
|
- 新增 `repayMethod`
|
||||||
|
- `isTradeConstruction` 改为 `isTradeBuildEnt`
|
||||||
|
- 删除 `省农担担保贷款`、`科技型企业`
|
||||||
|
- `loanTerm` 文案改为按年
|
||||||
|
- `collType` 选项改为 `一类/二类/三类/四类`
|
||||||
|
- `isGreenLoan`、`isTradeBuildEnt`、`collThirdParty` 提交值改为 `1/0`
|
||||||
|
- 企业详情左侧关键信息:
|
||||||
|
- 标签改为 `最终测算利率`
|
||||||
|
- 读取 `corpOutput.finalCalculateRate`
|
||||||
|
- 企业流程详情业务信息:
|
||||||
|
- 新增展示 `repayMethod`
|
||||||
|
- 新增展示 `isTradeBuildEnt`
|
||||||
|
- 保留 `isGreenLoan`
|
||||||
|
- 移除不在本次口径内的企业业务展示
|
||||||
|
- 企业模型输出补齐展示:
|
||||||
|
- `repayMethod`
|
||||||
|
- `isTradeBuildEnt`
|
||||||
|
- `loanRateHistory`
|
||||||
|
- `minRateProduct`
|
||||||
|
- `smoothRange`
|
||||||
|
- `finalCalculateRate`
|
||||||
|
- `referenceRate`
|
||||||
|
- 企业模型输出移除展示:
|
||||||
|
- `isAgriGuar`
|
||||||
|
- `midEntTax`
|
||||||
|
- `cardOverdue`
|
||||||
|
|
||||||
|
## 测试脚本
|
||||||
|
- 新增:
|
||||||
|
- `ruoyi-ui/tests/corporate-create-input-params.test.js`
|
||||||
|
- `ruoyi-ui/tests/corporate-display-fields.test.js`
|
||||||
|
- 更新 `ruoyi-ui/package.json`,补充对应 npm scripts
|
||||||
|
|
||||||
|
## 验证
|
||||||
|
- `nvm use default` 后执行两个对公静态断言脚本
|
||||||
|
- 执行前端生产构建
|
||||||
|
- 启动前端页面并在浏览器中确认:
|
||||||
|
- 对公新增弹窗字段和选项正确
|
||||||
|
- 创建成功后列表刷新
|
||||||
|
- 企业详情页显示 `最终测算利率`
|
||||||
|
- 企业详情页和模型输出出现新增字段
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
# 本地 Tomcat 与 TongWeb 双产物实施记录
|
|
||||||
|
|
||||||
## 本次改动
|
|
||||||
|
|
||||||
- 将 `ruoyi-admin` 的主打包方式从 `war` 恢复为 `jar`
|
|
||||||
- 恢复 `spring-boot-maven-plugin` 的 `repackage`,保证本地可直接运行 `ruoyi-admin.jar`
|
|
||||||
- 在 `ruoyi-admin` 中增加附加 `war` 打包步骤,使 `mvn package` 同时产出:
|
|
||||||
- `ruoyi-admin.jar`
|
|
||||||
- `ruoyi-admin.war`
|
|
||||||
- 在 `war` 打包中排除内嵌 Tomcat 相关 jar,避免 TongWeb 部署时容器冲突
|
|
||||||
- 将 `bin/restart_java_backend.sh` 恢复为本地 `java -jar` 启动链路
|
|
||||||
- 保持 `bin/prod/restart_java.sh`、`bin/prod/deploy_from_package.sh` 继续消费 `ruoyi-admin.war`
|
|
||||||
- 更新 `bin/run.bat`,恢复为本地 `jar` 启动入口
|
|
||||||
- 新增设计文档 `doc/2026-04-13-local-tomcat-remote-tongweb-design.md`
|
|
||||||
- 新增实施计划 `doc/2026-04-13-local-tomcat-remote-tongweb-backend-plan.md`
|
|
||||||
|
|
||||||
## 验证结果
|
|
||||||
|
|
||||||
- 已执行 `sh bin/restart_java_backend_test.sh`
|
|
||||||
- 已执行 `sh bin/prod/restart_java_test.sh`
|
|
||||||
- 已执行 `sh bin/prod/deploy_from_package_test.sh`
|
|
||||||
- 已执行 `sh -n bin/restart_java_backend.sh`
|
|
||||||
- 已执行 `sh -n bin/prod/restart_java.sh`
|
|
||||||
- 已执行 `sh -n bin/prod/deploy_from_package.sh`
|
|
||||||
- 已执行 `mvn -pl ruoyi-admin -am clean package -DskipTests`
|
|
||||||
- 已确认产物:
|
|
||||||
- `ruoyi-admin/target/ruoyi-admin.jar`
|
|
||||||
- `ruoyi-admin/target/ruoyi-admin.war`
|
|
||||||
|
|
||||||
## 结果说明
|
|
||||||
|
|
||||||
- 本地开发运行继续使用内嵌 Tomcat,不要求本机安装 TongWeb
|
|
||||||
- 服务器部署继续使用 TongWeb,只消费 `war`
|
|
||||||
- 一次打包即可同时得到本地运行产物和 TongWeb 部署产物
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
# Tomcat 替换为东方通实施记录
|
|
||||||
|
|
||||||
## 本次改动
|
|
||||||
|
|
||||||
- 将 `ruoyi-admin` 打包方式从 `jar` 调整为 `war`
|
|
||||||
- 在 `ruoyi-admin` 中显式声明 `spring-boot-starter-tomcat` 为 `provided`
|
|
||||||
- 在 `ruoyi-framework`、`ruoyi-loan-pricing` 中排除 `spring-boot-starter-web` 传递进来的嵌入式 Tomcat
|
|
||||||
- 将 `ruoyi-common` 中的 `jakarta.servlet-api` 调整为 `provided`
|
|
||||||
- 删除 `application-dev.yml`、`application-uat.yml`、`application-pro.yml` 中仅对内嵌 Tomcat 生效的 `server.tomcat` 配置
|
|
||||||
- 将 `bin/prod/restart_java.sh` 从 `java -jar` 启停改为 TongWeb 启停与 `war` 同步
|
|
||||||
- 将 `bin/prod/deploy_from_package.sh`、`bin/prod/deploy_release.sh` 的后端交付物从 `ruoyi-admin.jar` 改为 `ruoyi-admin.war`
|
|
||||||
- 将 `bin/restart_java_backend.sh` 改为本地构建 `war` 并发布到 TongWeb
|
|
||||||
- 更新 `deploy/2026-03-31-local-nginx-java-install-manual.md`,将后端运行环境说明改为 TongWeb
|
|
||||||
- 新增后端实施计划 `doc/2026-04-13-tongweb-replace-tomcat-backend-plan.md`
|
|
||||||
|
|
||||||
## 验证结果
|
|
||||||
|
|
||||||
- 已执行 `sh bin/prod/restart_java_test.sh`
|
|
||||||
- 已执行 `sh bin/prod/deploy_from_package_test.sh`
|
|
||||||
- 已执行 `sh bin/restart_java_backend_test.sh`
|
|
||||||
|
|
||||||
## 说明
|
|
||||||
|
|
||||||
- 本次替换按当前项目 `Spring Boot 3 + Jakarta Servlet` 路线落地,要求实际使用的东方通版本能够承载 Jakarta 体系应用
|
|
||||||
- Nginx 入口和反向代理端口保持不变,仍通过 `63310` 转发到后端容器
|
|
||||||
@@ -1,105 +0,0 @@
|
|||||||
# RuoYi-Vue springboot2 基线迁移实施记录
|
|
||||||
|
|
||||||
## 本次完成内容
|
|
||||||
|
|
||||||
- 以 `RuoYi-Vue/springboot2` 为基线覆盖当前仓库的框架层:
|
|
||||||
- 根 `pom.xml`
|
|
||||||
- `ruoyi-admin`
|
|
||||||
- `ruoyi-common`
|
|
||||||
- `ruoyi-framework`
|
|
||||||
- `ruoyi-generator`
|
|
||||||
- `ruoyi-quartz`
|
|
||||||
- `ruoyi-system`
|
|
||||||
- `ruoyi-ui`
|
|
||||||
- `sql` 基础脚本
|
|
||||||
- 恢复并接回业务模块与业务页面:
|
|
||||||
- `ruoyi-loan-pricing`
|
|
||||||
- `ruoyi-ui/src/views/loanPricing`
|
|
||||||
- `ruoyi-ui/src/api/loanPricing`
|
|
||||||
- `ruoyi-ui/src/router/index.js` 中的业务路由
|
|
||||||
- `ruoyi-admin` 中的业务配置
|
|
||||||
- 将 `ruoyi-loan-pricing` 从 Boot 3 / Java 17 写法回退到 Boot 2 / Java 8 可编译形态:
|
|
||||||
- 移除 `springdoc` 注解和依赖
|
|
||||||
- 将 `jakarta.*` 改回 `javax.*`
|
|
||||||
- 将 `String.repeat` 改为 Java 8 兼容实现
|
|
||||||
- 将模型调用改为模块内 `RestTemplate + form-urlencoded`
|
|
||||||
- 补回当前项目的“无 Redis”本地缓存实现:
|
|
||||||
- `InMemoryCacheEntry`
|
|
||||||
- `InMemoryCacheStats`
|
|
||||||
- `InMemoryCacheStore`
|
|
||||||
- 本地缓存版 `RedisCache`
|
|
||||||
- 本地缓存版 `CacheController`
|
|
||||||
- 调整前端业务依赖与脚本:
|
|
||||||
- 恢复 `crypto-js`
|
|
||||||
- 恢复 `splitpanes`
|
|
||||||
- 恢复 `ruoyi-ui/tests` 下 4 个业务测试脚本
|
|
||||||
- 恢复项目原有部署辅助脚本:
|
|
||||||
- `bin/prod/*.sh`
|
|
||||||
- `bin/restart_java_backend*.sh`
|
|
||||||
- 修正本地启动所需配置:
|
|
||||||
- `logback.xml` 日志目录改为项目内 `logs`
|
|
||||||
- `application.yml` 补齐 `swagger`、`redis`、`mybatis`
|
|
||||||
- 增加 `ruoyi-loan-pricing` 模块挂载和依赖声明
|
|
||||||
|
|
||||||
## 验证结果
|
|
||||||
|
|
||||||
### 后端编译验证
|
|
||||||
|
|
||||||
已通过:
|
|
||||||
|
|
||||||
- `export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_202.jdk/Contents/Home && export PATH="$JAVA_HOME/bin:$PATH" && mvn -pl ruoyi-admin -am -DskipTests package`
|
|
||||||
- `export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_202.jdk/Contents/Home && export PATH="$JAVA_HOME/bin:$PATH" && mvn -pl ruoyi-admin -am install -DskipTests`
|
|
||||||
|
|
||||||
### 前端构建验证
|
|
||||||
|
|
||||||
已通过:
|
|
||||||
|
|
||||||
- `source ~/.nvm/nvm.sh && nvm use 14.21.3 && npm install`
|
|
||||||
- `source ~/.nvm/nvm.sh && nvm use 14.21.3 && npm run build:prod`
|
|
||||||
|
|
||||||
### 前后端联调验证
|
|
||||||
|
|
||||||
已验证:
|
|
||||||
|
|
||||||
- 前端开发服务成功启动于 `http://localhost:1024`
|
|
||||||
- 浏览器打开 `http://localhost:1024/login`,页面标题显示为“若依管理系统”
|
|
||||||
- 浏览器点击登录后成功进入 `/index`
|
|
||||||
- 页面已实际渲染“流程列表”业务页面
|
|
||||||
- 通过前端代理访问 `http://localhost:1024/dev-api/captchaImage` 返回:
|
|
||||||
- `{"msg":"操作成功","code":200,"captchaEnabled":false}`
|
|
||||||
- 源码态后端在 `Java 8 + spring-boot:run` 模式下可启动成功
|
|
||||||
- 登录接口可成功返回 token:
|
|
||||||
- `POST /login`
|
|
||||||
|
|
||||||
## 联调中发现的遗留问题
|
|
||||||
|
|
||||||
浏览器进入系统后,页面出现两条后端错误提示:
|
|
||||||
|
|
||||||
1. 数据库缺少 `sys_notice_read` 表
|
|
||||||
2. `GET /loanPricing/workflow/list` 仍返回 `TooManyResultsException`
|
|
||||||
|
|
||||||
其中第 1 项已确认当前仓库 SQL 中已有对应建表语句:
|
|
||||||
|
|
||||||
- `sql/ry_20260330.sql`
|
|
||||||
- `sql/loan_pricing_prod_init_20260331.sql`
|
|
||||||
|
|
||||||
说明当前代码迁移已落地,但联调数据库尚未完全补齐到 `springboot2` 基线所需表结构。
|
|
||||||
|
|
||||||
第 2 项已经定位到当前运行态仍存在列表查询返回值与 MyBatis 映射结果不一致的问题,表现为:
|
|
||||||
|
|
||||||
- `GET /loanPricing/workflow/list?pageNum=1&pageSize=10`
|
|
||||||
- 返回:`{"msg":"nested exception is org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 15","code":500}`
|
|
||||||
|
|
||||||
## 结论
|
|
||||||
|
|
||||||
本次代码迁移已经完成:
|
|
||||||
|
|
||||||
- 框架层已切回 `RuoYi-Vue springboot2`
|
|
||||||
- 业务模块和业务页面已接回
|
|
||||||
- Java 8 / Spring Boot 2 / Vue 2 的编译与构建链路已打通
|
|
||||||
- 浏览器已成功进入业务页面与登录链路
|
|
||||||
|
|
||||||
当前剩余问题集中在:
|
|
||||||
|
|
||||||
- 联调数据库尚未补齐 `sys_notice_read` 表
|
|
||||||
- `workflow/list` 运行态查询仍需继续收口
|
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
# 上虞对公利率测算字段对齐实施记录
|
||||||
|
|
||||||
|
## 修改时间
|
||||||
|
- 2026-04-16
|
||||||
|
|
||||||
|
## 修改内容
|
||||||
|
- 对齐对公创建请求字段,新增 `repayMethod`,将 `isTradeConstruction` 统一为 `isTradeBuildEnt`
|
||||||
|
- 对齐企业详情返回与页面展示,左侧主利率改为 `finalCalculateRate`
|
||||||
|
- 对齐对公模型输出字段,补齐 `loanRateHistory`、`minRateProduct`、`smoothRange`、`finalCalculateRate`、`referenceRate`
|
||||||
|
- 裁剪企业模型输出和页面展示,不再暴露 `isAgriGuar`、`midEntTax`、`cardOverdue`
|
||||||
|
- 对公新增弹窗中的 `贷款期限(年)` 调整为下拉框,选项固定为 `1-10` 年
|
||||||
|
- 更新企业 mock 返回和 SQL 基线、迁移脚本
|
||||||
|
|
||||||
|
## 文档与脚本
|
||||||
|
- `doc/2026-04-16-shangyu-corporate-alignment-backend-plan.md`
|
||||||
|
- `doc/2026-04-16-shangyu-corporate-alignment-frontend-plan.md`
|
||||||
|
- `sql/2026-04-16-shangyu-corporate-alignment.sql`
|
||||||
|
|
||||||
|
## 验证记录
|
||||||
|
- 后端单测:
|
||||||
|
- `mvn -pl ruoyi-loan-pricing -Dtest=ModelCorpOutputFieldsTest,LoanPricingModelServiceTest,LoanPricingWorkflowServiceImplTest test`
|
||||||
|
- 结果:13 个测试全部通过
|
||||||
|
- 前端静态断言:
|
||||||
|
- `zsh -lic 'nvm use default >/dev/null && npm --prefix ruoyi-ui run test:corporate-create-input-params'`
|
||||||
|
- `zsh -lic 'nvm use default >/dev/null && npm --prefix ruoyi-ui run test:corporate-display-fields'`
|
||||||
|
- 结果:两个脚本均通过
|
||||||
|
- 前端构建:
|
||||||
|
- `zsh -lic 'nvm use default >/dev/null && npm --prefix ruoyi-ui run build:prod'`
|
||||||
|
- 结果:构建成功,仅有体积告警
|
||||||
|
- 接口联调:
|
||||||
|
- 使用 `/login/test` 获取 token
|
||||||
|
- 验证了对公创建正常场景、缺少 `repayMethod` 的参数错误场景、`分期/不分期` 与 `1/0` 分支场景
|
||||||
|
- 详情接口确认返回新增字段,且 `loanPricingWorkflow.loanRate = modelCorpOutputFields.finalCalculateRate`
|
||||||
|
- 浏览器联调:
|
||||||
|
- 启动前端开发服务并打开流程列表
|
||||||
|
- 验证对公新增弹窗字段、选项、提交流程
|
||||||
|
- 验证创建后列表新增记录
|
||||||
|
- 验证企业详情页出现 `最终测算利率`、`还款方式`、`贸易和建筑业企业`、`历史利率`、`产品最低利率下限`、`平滑幅度`、`参考利率`
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
# 流程详情页模型输出平铺展示实施记录
|
||||||
|
|
||||||
|
## 改动日期
|
||||||
|
- 2026-04-16
|
||||||
|
|
||||||
|
## 改动范围
|
||||||
|
- 前端:`ruoyi-ui/src/views/loanPricing/workflow/components/ModelOutputDisplay.vue`
|
||||||
|
- 前端测试:`ruoyi-ui/tests/model-output-flat-display.test.js`
|
||||||
|
- 前端脚本:`ruoyi-ui/package.json`
|
||||||
|
|
||||||
|
## 改动内容
|
||||||
|
- 取消流程详情页“模型输出”区域的 Tab 切换结构。
|
||||||
|
- 保留原有分组顺序与字段内容,将“基本信息”“忠诚度分析”“贡献度分析”等分组改为自上而下平铺展示。
|
||||||
|
- 按最新要求,将“测算结果”分组前移到“基本信息”下方,优先展示最终测算相关结果。
|
||||||
|
- 按最新要求,将“测算结果”中的“最终测算利率”调整到最后一行展示。
|
||||||
|
- 移除组件内仅用于 Tab 默认选中的 `activeTab` 和相关监听逻辑。
|
||||||
|
- 新增最小回归测试,校验模型输出组件不再包含 `el-tabs`、`el-tab-pane`,并具备平铺分组区块,同时校验“基本信息”后紧跟“测算结果”。
|
||||||
|
|
||||||
|
## 验证计划
|
||||||
|
- 使用 `nvm` 显式切换前端 Node 版本后执行 `npm run test:model-output-flat-display`。
|
||||||
|
- 启动前端页面,在浏览器中打开流程详情页,确认模型输出区域已按分组平铺展示,且不再出现 Tab 切换。
|
||||||
BIN
doc/~$上虞对公利率测算_上传字段与展示字段 .xlsx
Normal file
BIN
doc/~$上虞对公利率测算_上传字段与展示字段 .xlsx
Normal file
Binary file not shown.
BIN
doc/上虞对公利率测算_上传字段与展示字段 .xlsx
Normal file
BIN
doc/上虞对公利率测算_上传字段与展示字段 .xlsx
Normal file
Binary file not shown.
@@ -0,0 +1,27 @@
|
|||||||
|
# TongWeb 接入后端实施文档
|
||||||
|
|
||||||
|
## 目标
|
||||||
|
|
||||||
|
按照 `tongweb/2026-04-16-TongWeb接入全流程通用指南.md` 在当前后端工程中接入东方通 TongWeb,替换默认内嵌 Tomcat,并将 license 文件随 `ruoyi-admin` 启动模块一起打包。
|
||||||
|
|
||||||
|
## 实施内容
|
||||||
|
|
||||||
|
1. 在 `ruoyi-admin/pom.xml` 增加 TongWeb Maven 仓库。
|
||||||
|
2. 在 `ruoyi-admin/pom.xml` 对 `ruoyi-framework`、`ruoyi-loan-pricing` 依赖排除 `spring-boot-starter-tomcat`。
|
||||||
|
3. 在 `ruoyi-admin/pom.xml` 引入 `com.tongweb.springboot:tongweb-spring-boot-starter-3.x:7.0.E.7`。
|
||||||
|
4. 将 TongWeb license 复制到 `ruoyi-admin/src/main/resources/license.dat`,并在 `application.yml` 中配置 `server.tongweb.license.path=classpath:license.dat`。
|
||||||
|
5. 增加资源存在性测试,验证 `license.dat` 可从 classpath 加载。
|
||||||
|
6. 执行后端构建、依赖树、打包产物和测试验证,确认 TongWeb 依赖与 license 已正确接入。
|
||||||
|
|
||||||
|
## 变更说明
|
||||||
|
|
||||||
|
- 当前项目基于 Spring Boot 3.5.x,因此实际接入使用 `tongweb-spring-boot-starter-3.x`,版本号延续指南中的 `7.0.E.7`。
|
||||||
|
- license 按本次要求保持文件名为 `license.dat`,不改名为 `Tongweb_license.dat`。
|
||||||
|
- 现有 `application-dev.yml`、`application-pro.yml`、`application-uat.yml` 中的 `server.tomcat` 参数暂时保留,后续以 TongWeb 实际启动结果为准决定是否继续清理。
|
||||||
|
|
||||||
|
## 验证步骤
|
||||||
|
|
||||||
|
1. `mvn -pl ruoyi-admin -Dtest=TongWebLicenseResourceTest test`
|
||||||
|
2. `mvn -pl ruoyi-admin -am package -DskipTests`
|
||||||
|
3. `jar tf ruoyi-admin/target/ruoyi-admin.jar | rg 'license.dat|tongweb'`
|
||||||
|
4. `mvn -pl ruoyi-admin dependency:tree '-Dincludes=com.tongweb.springboot:*,com.tongweb:*,org.springframework.boot:spring-boot-starter-tomcat,org.apache.tomcat.embed:*'`
|
||||||
147
pom.xml
147
pom.xml
@@ -6,106 +6,54 @@
|
|||||||
|
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<artifactId>ruoyi</artifactId>
|
<artifactId>ruoyi</artifactId>
|
||||||
<version>3.9.2</version>
|
<version>3.9.1</version>
|
||||||
|
|
||||||
<name>ruoyi</name>
|
<name>ruoyi</name>
|
||||||
<url>http://www.ruoyi.vip</url>
|
<url>http://www.ruoyi.vip</url>
|
||||||
<description>若依管理系统</description>
|
<description>若依管理系统</description>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<ruoyi.version>3.9.2</ruoyi.version>
|
<ruoyi.version>3.9.1</ruoyi.version>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||||
<java.version>1.8</java.version>
|
<java.version>17</java.version>
|
||||||
<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
|
<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
|
||||||
<spring-boot.version>2.5.15</spring-boot.version>
|
<mybatis-spring-boot.version>3.0.5</mybatis-spring-boot.version>
|
||||||
<druid.version>1.2.28</druid.version>
|
<druid.version>1.2.27</druid.version>
|
||||||
<yauaa.version>7.32.0</yauaa.version>
|
<yauaa.version>7.32.0</yauaa.version>
|
||||||
<swagger.version>3.0.0</swagger.version>
|
<swagger.version>3.0.0</swagger.version>
|
||||||
<kaptcha.version>2.3.3</kaptcha.version>
|
<kaptcha.version>2.3.3</kaptcha.version>
|
||||||
<pagehelper.boot.version>1.4.7</pagehelper.boot.version>
|
<pagehelper.boot.version>2.1.1</pagehelper.boot.version>
|
||||||
<fastjson.version>2.0.61</fastjson.version>
|
<fastjson.version>2.0.60</fastjson.version>
|
||||||
<oshi.version>6.10.0</oshi.version>
|
<oshi.version>6.9.1</oshi.version>
|
||||||
<commons.io.version>2.21.0</commons.io.version>
|
<commons.io.version>2.21.0</commons.io.version>
|
||||||
<poi.version>4.1.2</poi.version>
|
<poi.version>4.1.2</poi.version>
|
||||||
<velocity.version>2.3</velocity.version>
|
<velocity.version>2.3</velocity.version>
|
||||||
<jwt.version>0.9.1</jwt.version>
|
<jwt.version>0.9.1</jwt.version>
|
||||||
<mybatis-plus.version>3.5.7</mybatis-plus.version>
|
<quartz.version>2.5.2</quartz.version>
|
||||||
<jsqlparser.version>4.5</jsqlparser.version>
|
<mysql.version>8.2.0</mysql.version>
|
||||||
<!-- override dependency version -->
|
<jaxb-api.version>2.3.1</jaxb-api.version>
|
||||||
<tomcat.version>9.0.112</tomcat.version>
|
<jakarta.version>6.0.0</jakarta.version>
|
||||||
<logback.version>1.2.13</logback.version>
|
<springdoc.version>2.8.14</springdoc.version>
|
||||||
<spring-security.version>5.7.14</spring-security.version>
|
|
||||||
<spring-framework.version>5.3.39</spring-framework.version>
|
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<!-- 依赖声明 -->
|
<!-- 依赖声明 -->
|
||||||
<dependencyManagement>
|
<dependencyManagement>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
|
||||||
<!-- 覆盖SpringFramework的依赖配置-->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework</groupId>
|
|
||||||
<artifactId>spring-framework-bom</artifactId>
|
|
||||||
<version>${spring-framework.version}</version>
|
|
||||||
<type>pom</type>
|
|
||||||
<scope>import</scope>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- 覆盖SpringSecurity的依赖配置-->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.security</groupId>
|
|
||||||
<artifactId>spring-security-bom</artifactId>
|
|
||||||
<version>${spring-security.version}</version>
|
|
||||||
<type>pom</type>
|
|
||||||
<scope>import</scope>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- SpringBoot的依赖配置-->
|
<!-- SpringBoot的依赖配置-->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-dependencies</artifactId>
|
<artifactId>spring-boot-dependencies</artifactId>
|
||||||
<version>${spring-boot.version}</version>
|
<version>3.5.8</version>
|
||||||
<type>pom</type>
|
<type>pom</type>
|
||||||
<scope>import</scope>
|
<scope>import</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- 覆盖logback的依赖配置-->
|
|
||||||
<dependency>
|
|
||||||
<groupId>ch.qos.logback</groupId>
|
|
||||||
<artifactId>logback-core</artifactId>
|
|
||||||
<version>${logback.version}</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>ch.qos.logback</groupId>
|
|
||||||
<artifactId>logback-classic</artifactId>
|
|
||||||
<version>${logback.version}</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- 覆盖tomcat的依赖配置-->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.tomcat.embed</groupId>
|
|
||||||
<artifactId>tomcat-embed-core</artifactId>
|
|
||||||
<version>${tomcat.version}</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.tomcat.embed</groupId>
|
|
||||||
<artifactId>tomcat-embed-el</artifactId>
|
|
||||||
<version>${tomcat.version}</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.tomcat.embed</groupId>
|
|
||||||
<artifactId>tomcat-embed-websocket</artifactId>
|
|
||||||
<version>${tomcat.version}</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- 阿里数据库连接池 -->
|
<!-- 阿里数据库连接池 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.alibaba</groupId>
|
<groupId>com.alibaba</groupId>
|
||||||
<artifactId>druid-spring-boot-starter</artifactId>
|
<artifactId>druid-spring-boot-3-starter</artifactId>
|
||||||
<version>${druid.version}</version>
|
<version>${druid.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
@@ -123,6 +71,30 @@
|
|||||||
<version>${pagehelper.boot.version}</version>
|
<version>${pagehelper.boot.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<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>${mysql.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>javax.xml.bind</groupId>
|
||||||
|
<artifactId>jaxb-api</artifactId>
|
||||||
|
<version>${jaxb-api.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>jakarta.servlet</groupId>
|
||||||
|
<artifactId>jakarta.servlet-api</artifactId>
|
||||||
|
<version>${jakarta.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- 获取系统信息 -->
|
<!-- 获取系统信息 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.github.oshi</groupId>
|
<groupId>com.github.oshi</groupId>
|
||||||
@@ -130,17 +102,11 @@
|
|||||||
<version>${oshi.version}</version>
|
<version>${oshi.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- Swagger3依赖 -->
|
<!-- spring-doc -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.springfox</groupId>
|
<groupId>org.springdoc</groupId>
|
||||||
<artifactId>springfox-boot-starter</artifactId>
|
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
|
||||||
<version>${swagger.version}</version>
|
<version>${springdoc.version}</version>
|
||||||
<exclusions>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>io.swagger</groupId>
|
|
||||||
<artifactId>swagger-models</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
</exclusions>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- io常用工具类 -->
|
<!-- io常用工具类 -->
|
||||||
@@ -164,6 +130,13 @@
|
|||||||
<version>${velocity.version}</version>
|
<version>${velocity.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- 定时任务 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.quartz-scheduler</groupId>
|
||||||
|
<artifactId>quartz</artifactId>
|
||||||
|
<version>${quartz.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- 阿里JSON解析器 -->
|
<!-- 阿里JSON解析器 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.alibaba.fastjson2</groupId>
|
<groupId>com.alibaba.fastjson2</groupId>
|
||||||
@@ -227,18 +200,6 @@
|
|||||||
<version>${ruoyi.version}</version>
|
<version>${ruoyi.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.baomidou</groupId>
|
|
||||||
<artifactId>mybatis-plus-boot-starter</artifactId>
|
|
||||||
<version>${mybatis-plus.version}</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.github.jsqlparser</groupId>
|
|
||||||
<artifactId>jsqlparser</artifactId>
|
|
||||||
<version>${jsqlparser.version}</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</dependencyManagement>
|
</dependencyManagement>
|
||||||
|
|
||||||
@@ -258,13 +219,19 @@
|
|||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
<version>3.1</version>
|
<version>3.13.0</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
|
<parameters>true</parameters>
|
||||||
<source>${java.version}</source>
|
<source>${java.version}</source>
|
||||||
<target>${java.version}</target>
|
<target>${java.version}</target>
|
||||||
<encoding>${project.build.sourceEncoding}</encoding>
|
<encoding>${project.build.sourceEncoding}</encoding>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
|
<version>3.3.0</version>
|
||||||
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
|
|||||||
BIN
ruoyi-admin/.DS_Store
vendored
Normal file
BIN
ruoyi-admin/.DS_Store
vendored
Normal file
Binary file not shown.
@@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>ruoyi</artifactId>
|
<artifactId>ruoyi</artifactId>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<version>3.9.2</version>
|
<version>3.9.1</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
@@ -15,6 +15,20 @@
|
|||||||
web服务入口
|
web服务入口
|
||||||
</description>
|
</description>
|
||||||
|
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<id>tongweb-releases</id>
|
||||||
|
<name>TongWeb Maven Releases</name>
|
||||||
|
<url>https://mvn.elitescloud.com/nexus/repository/maven-releases/</url>
|
||||||
|
<releases>
|
||||||
|
<enabled>true</enabled>
|
||||||
|
</releases>
|
||||||
|
<snapshots>
|
||||||
|
<enabled>false</enabled>
|
||||||
|
</snapshots>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
|
||||||
<!-- spring-boot-devtools -->
|
<!-- spring-boot-devtools -->
|
||||||
@@ -24,29 +38,28 @@
|
|||||||
<optional>true</optional> <!-- 表示依赖不会传递 -->
|
<optional>true</optional> <!-- 表示依赖不会传递 -->
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- swagger3-->
|
<!-- spring-doc -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.springfox</groupId>
|
<groupId>org.springdoc</groupId>
|
||||||
<artifactId>springfox-boot-starter</artifactId>
|
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- 防止进入swagger页面报类型转换错误,排除3.0.0中的引用,手动增加1.6.2版本 -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.swagger</groupId>
|
|
||||||
<artifactId>swagger-models</artifactId>
|
|
||||||
<version>1.6.2</version>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- Mysql驱动包 -->
|
<!-- Mysql驱动包 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>mysql</groupId>
|
<groupId>com.mysql</groupId>
|
||||||
<artifactId>mysql-connector-java</artifactId>
|
<artifactId>mysql-connector-j</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- 核心模块-->
|
<!-- 核心模块-->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<artifactId>ruoyi-framework</artifactId>
|
<artifactId>ruoyi-framework</artifactId>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-tomcat</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- 定时任务-->
|
<!-- 定时任务-->
|
||||||
@@ -65,6 +78,24 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<artifactId>ruoyi-loan-pricing</artifactId>
|
<artifactId>ruoyi-loan-pricing</artifactId>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-tomcat</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.tongweb.springboot</groupId>
|
||||||
|
<artifactId>tongweb-spring-boot-starter-3.x</artifactId>
|
||||||
|
<version>7.0.E.7</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
@@ -74,9 +105,9 @@
|
|||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
<version>2.5.15</version>
|
<version>3.5.4</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<fork>true</fork> <!-- 如果没有该配置,devtools不会生效 -->
|
<addResources>true</addResources>
|
||||||
</configuration>
|
</configuration>
|
||||||
<executions>
|
<executions>
|
||||||
<execution>
|
<execution>
|
||||||
|
|||||||
@@ -3,9 +3,9 @@ package com.ruoyi.web.controller.common;
|
|||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import javax.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.util.FastByteArrayOutputStream;
|
import org.springframework.util.FastByteArrayOutputStream;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ package com.ruoyi.web.controller.common;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|||||||
@@ -7,13 +7,6 @@ import com.ruoyi.common.core.domain.AjaxResult;
|
|||||||
import com.ruoyi.common.core.redis.RedisCache;
|
import com.ruoyi.common.core.redis.RedisCache;
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
import com.ruoyi.system.domain.SysCache;
|
import com.ruoyi.system.domain.SysCache;
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
|
||||||
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.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@@ -22,24 +15,33 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
|
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.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 缓存监控
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
*/
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/monitor/cache")
|
@RequestMapping("/monitor/cache")
|
||||||
public class CacheController
|
public class CacheController
|
||||||
{
|
{
|
||||||
private final RedisCache redisCache;
|
private final RedisCache redisCache;
|
||||||
|
|
||||||
private static final List<SysCache> CACHES = new ArrayList<SysCache>();
|
private final static List<SysCache> caches = new ArrayList<SysCache>();
|
||||||
|
|
||||||
static
|
|
||||||
{
|
{
|
||||||
CACHES.add(new SysCache(CacheConstants.LOGIN_TOKEN_KEY, "用户信息"));
|
caches.add(new SysCache(CacheConstants.LOGIN_TOKEN_KEY, "用户信息"));
|
||||||
CACHES.add(new SysCache(CacheConstants.SYS_CONFIG_KEY, "配置信息"));
|
caches.add(new SysCache(CacheConstants.SYS_CONFIG_KEY, "配置信息"));
|
||||||
CACHES.add(new SysCache(CacheConstants.SYS_DICT_KEY, "数据字典"));
|
caches.add(new SysCache(CacheConstants.SYS_DICT_KEY, "数据字典"));
|
||||||
CACHES.add(new SysCache(CacheConstants.CAPTCHA_CODE_KEY, "验证码"));
|
caches.add(new SysCache(CacheConstants.CAPTCHA_CODE_KEY, "验证码"));
|
||||||
CACHES.add(new SysCache(CacheConstants.REPEAT_SUBMIT_KEY, "防重提交"));
|
caches.add(new SysCache(CacheConstants.REPEAT_SUBMIT_KEY, "防重提交"));
|
||||||
CACHES.add(new SysCache(CacheConstants.RATE_LIMIT_KEY, "限流处理"));
|
caches.add(new SysCache(CacheConstants.RATE_LIMIT_KEY, "限流处理"));
|
||||||
CACHES.add(new SysCache(CacheConstants.PWD_ERR_CNT_KEY, "密码错误次数"));
|
caches.add(new SysCache(CacheConstants.PWD_ERR_CNT_KEY, "密码错误次数"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public CacheController(RedisCache redisCache)
|
public CacheController(RedisCache redisCache)
|
||||||
@@ -53,23 +55,23 @@ public class CacheController
|
|||||||
{
|
{
|
||||||
InMemoryCacheStats stats = redisCache.getCacheStats();
|
InMemoryCacheStats stats = redisCache.getCacheStats();
|
||||||
Map<String, Object> info = new LinkedHashMap<>();
|
Map<String, Object> info = new LinkedHashMap<>();
|
||||||
info.put("cache_type", stats.getCacheType());
|
info.put("cache_type", stats.cacheType());
|
||||||
info.put("cache_mode", stats.getMode());
|
info.put("cache_mode", stats.mode());
|
||||||
info.put("key_size", stats.getKeySize());
|
info.put("key_size", stats.keySize());
|
||||||
info.put("hit_count", stats.getHitCount());
|
info.put("hit_count", stats.hitCount());
|
||||||
info.put("miss_count", stats.getMissCount());
|
info.put("miss_count", stats.missCount());
|
||||||
info.put("expired_count", stats.getExpiredCount());
|
info.put("expired_count", stats.expiredCount());
|
||||||
info.put("write_count", stats.getWriteCount());
|
info.put("write_count", stats.writeCount());
|
||||||
|
|
||||||
Map<String, Object> result = new HashMap<>(3);
|
Map<String, Object> result = new HashMap<>(3);
|
||||||
result.put("info", info);
|
result.put("info", info);
|
||||||
result.put("dbSize", stats.getKeySize());
|
result.put("dbSize", stats.keySize());
|
||||||
|
|
||||||
List<Map<String, String>> pieList = new ArrayList<>();
|
List<Map<String, String>> pieList = new ArrayList<>();
|
||||||
pieList.add(statEntry("hit_count", stats.getHitCount()));
|
pieList.add(statEntry("hit_count", stats.hitCount()));
|
||||||
pieList.add(statEntry("miss_count", stats.getMissCount()));
|
pieList.add(statEntry("miss_count", stats.missCount()));
|
||||||
pieList.add(statEntry("expired_count", stats.getExpiredCount()));
|
pieList.add(statEntry("expired_count", stats.expiredCount()));
|
||||||
pieList.add(statEntry("write_count", stats.getWriteCount()));
|
pieList.add(statEntry("write_count", stats.writeCount()));
|
||||||
result.put("commandStats", pieList);
|
result.put("commandStats", pieList);
|
||||||
return AjaxResult.success(result);
|
return AjaxResult.success(result);
|
||||||
}
|
}
|
||||||
@@ -78,7 +80,7 @@ public class CacheController
|
|||||||
@GetMapping("/getNames")
|
@GetMapping("/getNames")
|
||||||
public AjaxResult cache()
|
public AjaxResult cache()
|
||||||
{
|
{
|
||||||
return AjaxResult.success(CACHES);
|
return AjaxResult.success(caches);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PreAuthorize("@ss.hasPermi('monitor:cache:list')")
|
@PreAuthorize("@ss.hasPermi('monitor:cache:list')")
|
||||||
@@ -137,9 +139,9 @@ public class CacheController
|
|||||||
{
|
{
|
||||||
return StringUtils.EMPTY;
|
return StringUtils.EMPTY;
|
||||||
}
|
}
|
||||||
if (cacheValue instanceof String)
|
if (cacheValue instanceof String stringValue)
|
||||||
{
|
{
|
||||||
return (String) cacheValue;
|
return stringValue;
|
||||||
}
|
}
|
||||||
return JSON.toJSONString(cacheValue);
|
return JSON.toJSONString(cacheValue);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package com.ruoyi.web.controller.monitor;
|
package com.ruoyi.web.controller.monitor;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package com.ruoyi.web.controller.monitor;
|
package com.ruoyi.web.controller.monitor;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package com.ruoyi.web.controller.system;
|
package com.ruoyi.web.controller.system;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package com.ruoyi.web.controller.system;
|
package com.ruoyi.web.controller.system;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import org.apache.commons.lang3.ArrayUtils;
|
import org.apache.commons.lang3.ArrayUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
@@ -111,20 +110,6 @@ public class SysDeptController extends BaseController
|
|||||||
return toAjax(deptService.updateDept(dept));
|
return toAjax(deptService.updateDept(dept));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 保存部门排序
|
|
||||||
*/
|
|
||||||
@PreAuthorize("@ss.hasPermi('system:dept:edit')")
|
|
||||||
@Log(title = "保存部门排序", businessType = BusinessType.UPDATE)
|
|
||||||
@PutMapping("/updateSort")
|
|
||||||
public AjaxResult updateSort(@RequestBody Map<String, String> params)
|
|
||||||
{
|
|
||||||
String[] deptIds = params.get("deptIds").split(",");
|
|
||||||
String[] orderNums = params.get("orderNums").split(",");
|
|
||||||
deptService.updateDeptSort(deptIds, orderNums);
|
|
||||||
return success();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除部门
|
* 删除部门
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package com.ruoyi.web.controller.system;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package com.ruoyi.web.controller.system;
|
package com.ruoyi.web.controller.system;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
|||||||
@@ -1,17 +1,10 @@
|
|||||||
package com.ruoyi.web.controller.system;
|
package com.ruoyi.web.controller.system;
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import com.ruoyi.common.config.RuoYiConfig;
|
import com.ruoyi.common.config.RuoYiConfig;
|
||||||
import com.ruoyi.common.core.domain.AjaxResult;
|
|
||||||
import com.ruoyi.common.core.domain.entity.SysUser;
|
|
||||||
import com.ruoyi.common.utils.SecurityUtils;
|
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
import com.ruoyi.system.service.ISysUserService;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 首页
|
* 首页
|
||||||
@@ -25,9 +18,6 @@ public class SysIndexController
|
|||||||
@Autowired
|
@Autowired
|
||||||
private RuoYiConfig ruoyiConfig;
|
private RuoYiConfig ruoyiConfig;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private ISysUserService userService;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 访问首页,提示语
|
* 访问首页,提示语
|
||||||
*/
|
*/
|
||||||
@@ -36,29 +26,4 @@ public class SysIndexController
|
|||||||
{
|
{
|
||||||
return StringUtils.format("欢迎使用{}后台管理框架,当前版本:v{},请通过前端地址访问。", ruoyiConfig.getName(), ruoyiConfig.getVersion());
|
return StringUtils.format("欢迎使用{}后台管理框架,当前版本:v{},请通过前端地址访问。", ruoyiConfig.getName(), ruoyiConfig.getVersion());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 解锁屏幕
|
|
||||||
*/
|
|
||||||
@PostMapping("/unlockscreen")
|
|
||||||
public AjaxResult unlockScreen(@RequestBody Map<String, String> body)
|
|
||||||
{
|
|
||||||
String password = body.get("password");
|
|
||||||
if (StringUtils.isEmpty(password))
|
|
||||||
{
|
|
||||||
return AjaxResult.error("密码不能为空");
|
|
||||||
}
|
|
||||||
String username = SecurityUtils.getUsername();
|
|
||||||
SysUser user = userService.selectUserByUserName(username);
|
|
||||||
if (user == null)
|
|
||||||
{
|
|
||||||
return AjaxResult.error("服务器超时,请重新登录");
|
|
||||||
}
|
|
||||||
if (!SecurityUtils.matchesPassword(password, user.getPassword()))
|
|
||||||
{
|
|
||||||
return AjaxResult.error("密码错误,请重新输入");
|
|
||||||
}
|
|
||||||
|
|
||||||
return AjaxResult.success("解锁成功");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import com.ruoyi.common.core.text.Convert;
|
|||||||
import com.ruoyi.common.utils.DateUtils;
|
import com.ruoyi.common.utils.DateUtils;
|
||||||
import com.ruoyi.common.utils.SecurityUtils;
|
import com.ruoyi.common.utils.SecurityUtils;
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
|
import com.ruoyi.framework.web.service.PasswordTransferCryptoService;
|
||||||
import com.ruoyi.framework.web.service.SysLoginService;
|
import com.ruoyi.framework.web.service.SysLoginService;
|
||||||
import com.ruoyi.framework.web.service.SysPermissionService;
|
import com.ruoyi.framework.web.service.SysPermissionService;
|
||||||
import com.ruoyi.framework.web.service.TokenService;
|
import com.ruoyi.framework.web.service.TokenService;
|
||||||
@@ -47,6 +48,9 @@ public class SysLoginController
|
|||||||
@Autowired
|
@Autowired
|
||||||
private ISysConfigService configService;
|
private ISysConfigService configService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private PasswordTransferCryptoService passwordTransferCryptoService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 登录方法
|
* 登录方法
|
||||||
*
|
*
|
||||||
@@ -57,6 +61,7 @@ public class SysLoginController
|
|||||||
public AjaxResult login(@RequestBody LoginBody loginBody)
|
public AjaxResult login(@RequestBody LoginBody loginBody)
|
||||||
{
|
{
|
||||||
AjaxResult ajax = AjaxResult.success();
|
AjaxResult ajax = AjaxResult.success();
|
||||||
|
loginBody.setPassword(passwordTransferCryptoService.decrypt(loginBody.getPassword()));
|
||||||
// 生成令牌
|
// 生成令牌
|
||||||
String token = loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(),
|
String token = loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(),
|
||||||
loginBody.getUuid());
|
loginBody.getUuid());
|
||||||
@@ -64,6 +69,22 @@ public class SysLoginController
|
|||||||
return ajax;
|
return ajax;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录方法
|
||||||
|
* 该方法处理用户登录请求,无需验证码
|
||||||
|
* @param loginBody 登录信息,包含用户名和密码
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
@PostMapping("/login/test")
|
||||||
|
public AjaxResult loginWithoutCaptcha (@RequestBody LoginBody loginBody)
|
||||||
|
{
|
||||||
|
AjaxResult ajax = AjaxResult.success();
|
||||||
|
// 生成令牌
|
||||||
|
String token = loginService.loginWithoutCaptcha(loginBody.getUsername(), loginBody.getPassword());
|
||||||
|
ajax.put(Constants.TOKEN, token);
|
||||||
|
return ajax;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取用户信息
|
* 获取用户信息
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package com.ruoyi.web.controller.system;
|
package com.ruoyi.web.controller.system;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
@@ -130,20 +129,6 @@ public class SysMenuController extends BaseController
|
|||||||
return toAjax(menuService.updateMenu(menu));
|
return toAjax(menuService.updateMenu(menu));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 保存菜单排序
|
|
||||||
*/
|
|
||||||
@PreAuthorize("@ss.hasPermi('system:menu:edit')")
|
|
||||||
@Log(title = "保存菜单排序", businessType = BusinessType.UPDATE)
|
|
||||||
@PutMapping("/updateSort")
|
|
||||||
public AjaxResult updateSort(@RequestBody Map<String, String> params)
|
|
||||||
{
|
|
||||||
String[] menuIds = params.get("menuIds").split(",");
|
|
||||||
String[] orderNums = params.get("orderNums").split(",");
|
|
||||||
menuService.updateMenuSort(menuIds, orderNums);
|
|
||||||
return success();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除菜单
|
* 删除菜单
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -11,16 +11,13 @@ import org.springframework.web.bind.annotation.PostMapping;
|
|||||||
import org.springframework.web.bind.annotation.PutMapping;
|
import org.springframework.web.bind.annotation.PutMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.ResponseBody;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import com.ruoyi.common.annotation.Log;
|
import com.ruoyi.common.annotation.Log;
|
||||||
import com.ruoyi.common.core.controller.BaseController;
|
import com.ruoyi.common.core.controller.BaseController;
|
||||||
import com.ruoyi.common.core.domain.AjaxResult;
|
import com.ruoyi.common.core.domain.AjaxResult;
|
||||||
import com.ruoyi.common.core.page.TableDataInfo;
|
import com.ruoyi.common.core.page.TableDataInfo;
|
||||||
import com.ruoyi.common.core.text.Convert;
|
|
||||||
import com.ruoyi.common.enums.BusinessType;
|
import com.ruoyi.common.enums.BusinessType;
|
||||||
import com.ruoyi.system.domain.SysNotice;
|
import com.ruoyi.system.domain.SysNotice;
|
||||||
import com.ruoyi.system.service.ISysNoticeReadService;
|
|
||||||
import com.ruoyi.system.service.ISysNoticeService;
|
import com.ruoyi.system.service.ISysNoticeService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -35,9 +32,6 @@ public class SysNoticeController extends BaseController
|
|||||||
@Autowired
|
@Autowired
|
||||||
private ISysNoticeService noticeService;
|
private ISysNoticeService noticeService;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private ISysNoticeReadService noticeReadService;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取通知公告列表
|
* 获取通知公告列表
|
||||||
*/
|
*/
|
||||||
@@ -84,46 +78,6 @@ public class SysNoticeController extends BaseController
|
|||||||
return toAjax(noticeService.updateNotice(notice));
|
return toAjax(noticeService.updateNotice(notice));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 首页顶部公告列表(返回全部正常公告,带当前用户已读标记,最多5条)
|
|
||||||
*/
|
|
||||||
@GetMapping("/listTop")
|
|
||||||
@ResponseBody
|
|
||||||
public AjaxResult listTop()
|
|
||||||
{
|
|
||||||
Long userId = getUserId();
|
|
||||||
List<SysNotice> list = noticeReadService.selectNoticeListWithReadStatus(userId, 5);
|
|
||||||
long unreadCount = list.stream().filter(n -> !n.getIsRead()).count();
|
|
||||||
AjaxResult result = AjaxResult.success(list);
|
|
||||||
result.put("unreadCount", unreadCount);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 标记公告已读
|
|
||||||
*/
|
|
||||||
@PostMapping("/markRead")
|
|
||||||
@ResponseBody
|
|
||||||
public AjaxResult markRead(Long noticeId)
|
|
||||||
{
|
|
||||||
Long userId = getUserId();
|
|
||||||
noticeReadService.markRead(noticeId, userId);
|
|
||||||
return success();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 批量标记已读
|
|
||||||
*/
|
|
||||||
@PostMapping("/markReadAll")
|
|
||||||
@ResponseBody
|
|
||||||
public AjaxResult markReadAll(String ids)
|
|
||||||
{
|
|
||||||
Long userId = getUserId();
|
|
||||||
Long[] noticeIds = Convert.toLongArray(ids);
|
|
||||||
noticeReadService.markReadBatch(userId, noticeIds);
|
|
||||||
return success();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除通知公告
|
* 删除通知公告
|
||||||
*/
|
*/
|
||||||
@@ -132,7 +86,6 @@ public class SysNoticeController extends BaseController
|
|||||||
@DeleteMapping("/{noticeIds}")
|
@DeleteMapping("/{noticeIds}")
|
||||||
public AjaxResult remove(@PathVariable Long[] noticeIds)
|
public AjaxResult remove(@PathVariable Long[] noticeIds)
|
||||||
{
|
{
|
||||||
noticeReadService.deleteByNoticeIds(noticeIds);
|
|
||||||
return toAjax(noticeService.deleteNoticeByIds(noticeIds));
|
return toAjax(noticeService.deleteNoticeByIds(noticeIds));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package com.ruoyi.web.controller.system;
|
package com.ruoyi.web.controller.system;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import com.ruoyi.common.utils.StringUtils;
|
|||||||
import com.ruoyi.common.utils.file.FileUploadUtils;
|
import com.ruoyi.common.utils.file.FileUploadUtils;
|
||||||
import com.ruoyi.common.utils.file.FileUtils;
|
import com.ruoyi.common.utils.file.FileUtils;
|
||||||
import com.ruoyi.common.utils.file.MimeTypeUtils;
|
import com.ruoyi.common.utils.file.MimeTypeUtils;
|
||||||
|
import com.ruoyi.framework.web.service.PasswordTransferCryptoService;
|
||||||
import com.ruoyi.framework.web.service.TokenService;
|
import com.ruoyi.framework.web.service.TokenService;
|
||||||
import com.ruoyi.system.service.ISysUserService;
|
import com.ruoyi.system.service.ISysUserService;
|
||||||
|
|
||||||
@@ -41,6 +42,9 @@ public class SysProfileController extends BaseController
|
|||||||
@Autowired
|
@Autowired
|
||||||
private TokenService tokenService;
|
private TokenService tokenService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private PasswordTransferCryptoService passwordTransferCryptoService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 个人信息
|
* 个人信息
|
||||||
*/
|
*/
|
||||||
@@ -92,8 +96,8 @@ public class SysProfileController extends BaseController
|
|||||||
@PutMapping("/updatePwd")
|
@PutMapping("/updatePwd")
|
||||||
public AjaxResult updatePwd(@RequestBody Map<String, String> params)
|
public AjaxResult updatePwd(@RequestBody Map<String, String> params)
|
||||||
{
|
{
|
||||||
String oldPassword = params.get("oldPassword");
|
String oldPassword = passwordTransferCryptoService.decrypt(params.get("oldPassword"));
|
||||||
String newPassword = params.get("newPassword");
|
String newPassword = passwordTransferCryptoService.decrypt(params.get("newPassword"));
|
||||||
LoginUser loginUser = getLoginUser();
|
LoginUser loginUser = getLoginUser();
|
||||||
Long userId = loginUser.getUserId();
|
Long userId = loginUser.getUserId();
|
||||||
SysUser user = userService.selectUserById(userId);
|
SysUser user = userService.selectUserById(userId);
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import com.ruoyi.common.core.controller.BaseController;
|
|||||||
import com.ruoyi.common.core.domain.AjaxResult;
|
import com.ruoyi.common.core.domain.AjaxResult;
|
||||||
import com.ruoyi.common.core.domain.model.RegisterBody;
|
import com.ruoyi.common.core.domain.model.RegisterBody;
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
|
import com.ruoyi.framework.web.service.PasswordTransferCryptoService;
|
||||||
import com.ruoyi.framework.web.service.SysRegisterService;
|
import com.ruoyi.framework.web.service.SysRegisterService;
|
||||||
import com.ruoyi.system.service.ISysConfigService;
|
import com.ruoyi.system.service.ISysConfigService;
|
||||||
|
|
||||||
@@ -25,6 +26,9 @@ public class SysRegisterController extends BaseController
|
|||||||
@Autowired
|
@Autowired
|
||||||
private ISysConfigService configService;
|
private ISysConfigService configService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private PasswordTransferCryptoService passwordTransferCryptoService;
|
||||||
|
|
||||||
@PostMapping("/register")
|
@PostMapping("/register")
|
||||||
public AjaxResult register(@RequestBody RegisterBody user)
|
public AjaxResult register(@RequestBody RegisterBody user)
|
||||||
{
|
{
|
||||||
@@ -32,6 +36,7 @@ public class SysRegisterController extends BaseController
|
|||||||
{
|
{
|
||||||
return error("当前系统没有开启注册功能!");
|
return error("当前系统没有开启注册功能!");
|
||||||
}
|
}
|
||||||
|
user.setPassword(passwordTransferCryptoService.decrypt(user.getPassword()));
|
||||||
String msg = registerService.register(user);
|
String msg = registerService.register(user);
|
||||||
return StringUtils.isEmpty(msg) ? success() : error(msg);
|
return StringUtils.isEmpty(msg) ? success() : error(msg);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package com.ruoyi.web.controller.system;
|
package com.ruoyi.web.controller.system;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package com.ruoyi.web.controller.system;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import org.apache.commons.lang3.ArrayUtils;
|
import org.apache.commons.lang3.ArrayUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
@@ -27,6 +27,7 @@ import com.ruoyi.common.enums.BusinessType;
|
|||||||
import com.ruoyi.common.utils.SecurityUtils;
|
import com.ruoyi.common.utils.SecurityUtils;
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
import com.ruoyi.common.utils.poi.ExcelUtil;
|
import com.ruoyi.common.utils.poi.ExcelUtil;
|
||||||
|
import com.ruoyi.framework.web.service.PasswordTransferCryptoService;
|
||||||
import com.ruoyi.system.service.ISysDeptService;
|
import com.ruoyi.system.service.ISysDeptService;
|
||||||
import com.ruoyi.system.service.ISysPostService;
|
import com.ruoyi.system.service.ISysPostService;
|
||||||
import com.ruoyi.system.service.ISysRoleService;
|
import com.ruoyi.system.service.ISysRoleService;
|
||||||
@@ -53,6 +54,9 @@ public class SysUserController extends BaseController
|
|||||||
@Autowired
|
@Autowired
|
||||||
private ISysPostService postService;
|
private ISysPostService postService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private PasswordTransferCryptoService passwordTransferCryptoService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取用户列表
|
* 获取用户列表
|
||||||
*/
|
*/
|
||||||
@@ -139,6 +143,7 @@ public class SysUserController extends BaseController
|
|||||||
return error("新增用户'" + user.getUserName() + "'失败,邮箱账号已存在");
|
return error("新增用户'" + user.getUserName() + "'失败,邮箱账号已存在");
|
||||||
}
|
}
|
||||||
user.setCreateBy(getUsername());
|
user.setCreateBy(getUsername());
|
||||||
|
user.setPassword(passwordTransferCryptoService.decrypt(user.getPassword()));
|
||||||
user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
|
user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
|
||||||
return toAjax(userService.insertUser(user));
|
return toAjax(userService.insertUser(user));
|
||||||
}
|
}
|
||||||
@@ -196,6 +201,7 @@ public class SysUserController extends BaseController
|
|||||||
{
|
{
|
||||||
userService.checkUserAllowed(user);
|
userService.checkUserAllowed(user);
|
||||||
userService.checkUserDataScope(user.getUserId());
|
userService.checkUserDataScope(user.getUserId());
|
||||||
|
user.setPassword(passwordTransferCryptoService.decrypt(user.getPassword()));
|
||||||
user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
|
user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
|
||||||
user.setUpdateBy(getUsername());
|
user.setUpdateBy(getUsername());
|
||||||
return toAjax(userService.resetPwd(user));
|
return toAjax(userService.resetPwd(user));
|
||||||
|
|||||||
@@ -15,19 +15,16 @@ import org.springframework.web.bind.annotation.RestController;
|
|||||||
import com.ruoyi.common.core.controller.BaseController;
|
import com.ruoyi.common.core.controller.BaseController;
|
||||||
import com.ruoyi.common.core.domain.R;
|
import com.ruoyi.common.core.domain.R;
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
import io.swagger.annotations.Api;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.annotations.ApiImplicitParam;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.annotations.ApiImplicitParams;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
import io.swagger.annotations.ApiModel;
|
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
|
||||||
import io.swagger.annotations.ApiOperation;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* swagger 用户测试方法
|
* swagger 用户测试方法
|
||||||
*
|
*
|
||||||
* @author ruoyi
|
* @author ruoyi
|
||||||
*/
|
*/
|
||||||
@Api("用户信息管理")
|
@Tag(name = "用户信息管理")
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/test/user")
|
@RequestMapping("/test/user")
|
||||||
public class TestController extends BaseController
|
public class TestController extends BaseController
|
||||||
@@ -38,7 +35,7 @@ public class TestController extends BaseController
|
|||||||
users.put(2, new UserEntity(2, "ry", "admin123", "15666666666"));
|
users.put(2, new UserEntity(2, "ry", "admin123", "15666666666"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ApiOperation("获取用户列表")
|
@Operation(summary = "获取用户列表")
|
||||||
@GetMapping("/list")
|
@GetMapping("/list")
|
||||||
public R<List<UserEntity>> userList()
|
public R<List<UserEntity>> userList()
|
||||||
{
|
{
|
||||||
@@ -46,10 +43,10 @@ public class TestController extends BaseController
|
|||||||
return R.ok(userList);
|
return R.ok(userList);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ApiOperation("获取用户详细")
|
@Operation(summary = "获取用户详细")
|
||||||
@ApiImplicitParam(name = "userId", value = "用户ID", required = true, dataType = "int", paramType = "path", dataTypeClass = Integer.class)
|
|
||||||
@GetMapping("/{userId}")
|
@GetMapping("/{userId}")
|
||||||
public R<UserEntity> getUser(@PathVariable Integer userId)
|
public R<UserEntity> getUser(@PathVariable(name = "userId")
|
||||||
|
Integer userId)
|
||||||
{
|
{
|
||||||
if (!users.isEmpty() && users.containsKey(userId))
|
if (!users.isEmpty() && users.containsKey(userId))
|
||||||
{
|
{
|
||||||
@@ -61,13 +58,7 @@ public class TestController extends BaseController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ApiOperation("新增用户")
|
@Operation(summary = "新增用户")
|
||||||
@ApiImplicitParams({
|
|
||||||
@ApiImplicitParam(name = "userId", value = "用户id", dataType = "Integer", dataTypeClass = Integer.class),
|
|
||||||
@ApiImplicitParam(name = "username", value = "用户名称", dataType = "String", dataTypeClass = String.class),
|
|
||||||
@ApiImplicitParam(name = "password", value = "用户密码", dataType = "String", dataTypeClass = String.class),
|
|
||||||
@ApiImplicitParam(name = "mobile", value = "用户手机", dataType = "String", dataTypeClass = String.class)
|
|
||||||
})
|
|
||||||
@PostMapping("/save")
|
@PostMapping("/save")
|
||||||
public R<String> save(UserEntity user)
|
public R<String> save(UserEntity user)
|
||||||
{
|
{
|
||||||
@@ -79,9 +70,10 @@ public class TestController extends BaseController
|
|||||||
return R.ok();
|
return R.ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ApiOperation("更新用户")
|
@Operation(summary = "更新用户")
|
||||||
@PutMapping("/update")
|
@PutMapping("/update")
|
||||||
public R<String> update(@RequestBody UserEntity user)
|
public R<String> update(@RequestBody
|
||||||
|
UserEntity user)
|
||||||
{
|
{
|
||||||
if (StringUtils.isNull(user) || StringUtils.isNull(user.getUserId()))
|
if (StringUtils.isNull(user) || StringUtils.isNull(user.getUserId()))
|
||||||
{
|
{
|
||||||
@@ -96,10 +88,10 @@ public class TestController extends BaseController
|
|||||||
return R.ok();
|
return R.ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ApiOperation("删除用户信息")
|
@Operation(summary = "删除用户信息")
|
||||||
@ApiImplicitParam(name = "userId", value = "用户ID", required = true, dataType = "int", paramType = "path", dataTypeClass = Integer.class)
|
|
||||||
@DeleteMapping("/{userId}")
|
@DeleteMapping("/{userId}")
|
||||||
public R<String> delete(@PathVariable Integer userId)
|
public R<String> delete(@PathVariable(name = "userId")
|
||||||
|
Integer userId)
|
||||||
{
|
{
|
||||||
if (!users.isEmpty() && users.containsKey(userId))
|
if (!users.isEmpty() && users.containsKey(userId))
|
||||||
{
|
{
|
||||||
@@ -113,19 +105,19 @@ public class TestController extends BaseController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ApiModel(value = "UserEntity", description = "用户实体")
|
@Schema(description = "用户实体")
|
||||||
class UserEntity
|
class UserEntity
|
||||||
{
|
{
|
||||||
@ApiModelProperty("用户ID")
|
@Schema(title = "用户ID")
|
||||||
private Integer userId;
|
private Integer userId;
|
||||||
|
|
||||||
@ApiModelProperty("用户名称")
|
@Schema(title = "用户名称")
|
||||||
private String username;
|
private String username;
|
||||||
|
|
||||||
@ApiModelProperty("用户密码")
|
@Schema(title = "用户密码")
|
||||||
private String password;
|
private String password;
|
||||||
|
|
||||||
@ApiModelProperty("用户手机")
|
@Schema(title = "用户手机")
|
||||||
private String mobile;
|
private String mobile;
|
||||||
|
|
||||||
public UserEntity()
|
public UserEntity()
|
||||||
|
|||||||
@@ -1,26 +1,15 @@
|
|||||||
package com.ruoyi.web.core.config;
|
package com.ruoyi.web.core.config;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import com.ruoyi.common.config.RuoYiConfig;
|
import com.ruoyi.common.config.RuoYiConfig;
|
||||||
import io.swagger.annotations.ApiOperation;
|
import io.swagger.v3.oas.models.Components;
|
||||||
import io.swagger.models.auth.In;
|
import io.swagger.v3.oas.models.OpenAPI;
|
||||||
import springfox.documentation.builders.ApiInfoBuilder;
|
import io.swagger.v3.oas.models.info.Contact;
|
||||||
import springfox.documentation.builders.PathSelectors;
|
import io.swagger.v3.oas.models.info.Info;
|
||||||
import springfox.documentation.builders.RequestHandlerSelectors;
|
import io.swagger.v3.oas.models.security.SecurityRequirement;
|
||||||
import springfox.documentation.service.ApiInfo;
|
import io.swagger.v3.oas.models.security.SecurityScheme;
|
||||||
import springfox.documentation.service.ApiKey;
|
|
||||||
import springfox.documentation.service.AuthorizationScope;
|
|
||||||
import springfox.documentation.service.Contact;
|
|
||||||
import springfox.documentation.service.SecurityReference;
|
|
||||||
import springfox.documentation.service.SecurityScheme;
|
|
||||||
import springfox.documentation.spi.DocumentationType;
|
|
||||||
import springfox.documentation.spi.service.contexts.SecurityContext;
|
|
||||||
import springfox.documentation.spring.web.plugins.Docket;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Swagger2的接口配置
|
* Swagger2的接口配置
|
||||||
@@ -34,92 +23,42 @@ public class SwaggerConfig
|
|||||||
@Autowired
|
@Autowired
|
||||||
private RuoYiConfig ruoyiConfig;
|
private RuoYiConfig ruoyiConfig;
|
||||||
|
|
||||||
/** 是否开启swagger */
|
|
||||||
@Value("${swagger.enabled}")
|
|
||||||
private boolean enabled;
|
|
||||||
|
|
||||||
/** 设置请求的统一前缀 */
|
|
||||||
@Value("${swagger.pathMapping}")
|
|
||||||
private String pathMapping;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建API
|
* 自定义的 OpenAPI 对象
|
||||||
*/
|
*/
|
||||||
@Bean
|
@Bean
|
||||||
public Docket createRestApi()
|
public OpenAPI customOpenApi()
|
||||||
{
|
{
|
||||||
return new Docket(DocumentationType.OAS_30)
|
return new OpenAPI().components(new Components()
|
||||||
// 是否启用Swagger
|
// 设置认证的请求头
|
||||||
.enable(enabled)
|
.addSecuritySchemes("apikey", securityScheme()))
|
||||||
// 用来创建该API的基本信息,展示在文档的页面中(自定义展示的信息)
|
.addSecurityItem(new SecurityRequirement().addList("apikey"))
|
||||||
.apiInfo(apiInfo())
|
.info(getApiInfo());
|
||||||
// 设置哪些接口暴露给Swagger展示
|
|
||||||
.select()
|
|
||||||
// 扫描所有有注解的api,用这种方式更灵活
|
|
||||||
.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
|
|
||||||
// 扫描指定包中的swagger注解
|
|
||||||
// .apis(RequestHandlerSelectors.basePackage("com.ruoyi.project.tool.swagger"))
|
|
||||||
// 扫描所有 .apis(RequestHandlerSelectors.any())
|
|
||||||
.paths(PathSelectors.any())
|
|
||||||
.build()
|
|
||||||
/* 设置安全模式,swagger可以设置访问token */
|
|
||||||
.securitySchemes(securitySchemes())
|
|
||||||
.securityContexts(securityContexts())
|
|
||||||
.pathMapping(pathMapping);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Bean
|
||||||
* 安全模式,这里指定token通过Authorization头请求头传递
|
public SecurityScheme securityScheme()
|
||||||
*/
|
|
||||||
private List<SecurityScheme> securitySchemes()
|
|
||||||
{
|
{
|
||||||
List<SecurityScheme> apiKeyList = new ArrayList<SecurityScheme>();
|
return new SecurityScheme()
|
||||||
apiKeyList.add(new ApiKey("Authorization", "Authorization", In.HEADER.toValue()));
|
.type(SecurityScheme.Type.APIKEY)
|
||||||
return apiKeyList;
|
.name("Authorization")
|
||||||
}
|
.in(SecurityScheme.In.HEADER)
|
||||||
|
.scheme("Bearer");
|
||||||
/**
|
|
||||||
* 安全上下文
|
|
||||||
*/
|
|
||||||
private List<SecurityContext> securityContexts()
|
|
||||||
{
|
|
||||||
List<SecurityContext> securityContexts = new ArrayList<>();
|
|
||||||
securityContexts.add(
|
|
||||||
SecurityContext.builder()
|
|
||||||
.securityReferences(defaultAuth())
|
|
||||||
.operationSelector(o -> o.requestMappingPattern().matches("/.*"))
|
|
||||||
.build());
|
|
||||||
return securityContexts;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 默认的安全上引用
|
|
||||||
*/
|
|
||||||
private List<SecurityReference> defaultAuth()
|
|
||||||
{
|
|
||||||
AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
|
|
||||||
AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
|
|
||||||
authorizationScopes[0] = authorizationScope;
|
|
||||||
List<SecurityReference> securityReferences = new ArrayList<>();
|
|
||||||
securityReferences.add(new SecurityReference("Authorization", authorizationScopes));
|
|
||||||
return securityReferences;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 添加摘要信息
|
* 添加摘要信息
|
||||||
*/
|
*/
|
||||||
private ApiInfo apiInfo()
|
public Info getApiInfo()
|
||||||
{
|
{
|
||||||
// 用ApiInfoBuilder进行定制
|
return new Info()
|
||||||
return new ApiInfoBuilder()
|
// 设置标题
|
||||||
// 设置标题
|
.title("标题:若依管理系统_接口文档")
|
||||||
.title("标题:若依管理系统_接口文档")
|
// 描述
|
||||||
// 描述
|
.description("描述:用于管理集团旗下公司的人员信息,具体包括XXX,XXX模块...")
|
||||||
.description("描述:用于管理集团旗下公司的人员信息,具体包括XXX,XXX模块...")
|
// 作者信息
|
||||||
// 作者信息
|
.contact(new Contact().name(ruoyiConfig.getName()))
|
||||||
.contact(new Contact(ruoyiConfig.getName(), null, null))
|
// 版本
|
||||||
// 版本
|
.version("版本号:" + ruoyiConfig.getVersion());
|
||||||
.version("版本号:" + ruoyiConfig.getVersion())
|
|
||||||
.build();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,61 +0,0 @@
|
|||||||
# 数据源配置
|
|
||||||
spring:
|
|
||||||
datasource:
|
|
||||||
type: com.alibaba.druid.pool.DruidDataSource
|
|
||||||
driverClassName: com.mysql.cj.jdbc.Driver
|
|
||||||
druid:
|
|
||||||
# 主库数据源
|
|
||||||
master:
|
|
||||||
url: jdbc:mysql://localhost:3306/ry-vue?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
|
|
||||||
@@ -1,9 +1,14 @@
|
|||||||
# 项目相关配置
|
# 项目相关配置
|
||||||
|
server:
|
||||||
|
tongweb:
|
||||||
|
license:
|
||||||
|
path: classpath:license.dat
|
||||||
|
|
||||||
ruoyi:
|
ruoyi:
|
||||||
# 名称
|
# 名称
|
||||||
name: RuoYi
|
name: RuoYi
|
||||||
# 版本
|
# 版本
|
||||||
version: 3.9.2
|
version: 3.9.1
|
||||||
# 版权年份
|
# 版权年份
|
||||||
copyrightYear: 2026
|
copyrightYear: 2026
|
||||||
# 文件路径 示例( Windows配置D:/ruoyi/uploadPath,Linux配置 /home/ruoyi/uploadPath)
|
# 文件路径 示例( Windows配置D:/ruoyi/uploadPath,Linux配置 /home/ruoyi/uploadPath)
|
||||||
@@ -49,19 +54,6 @@ spring:
|
|||||||
restart:
|
restart:
|
||||||
# 热部署开关
|
# 热部署开关
|
||||||
enabled: true
|
enabled: true
|
||||||
# redis 配置
|
|
||||||
redis:
|
|
||||||
host: localhost
|
|
||||||
port: 6379
|
|
||||||
database: 0
|
|
||||||
password:
|
|
||||||
timeout: 10s
|
|
||||||
lettuce:
|
|
||||||
pool:
|
|
||||||
min-idle: 0
|
|
||||||
max-idle: 8
|
|
||||||
max-active: 8
|
|
||||||
max-wait: -1ms
|
|
||||||
|
|
||||||
|
|
||||||
# token配置
|
# token配置
|
||||||
@@ -73,8 +65,8 @@ token:
|
|||||||
# 令牌有效期(默认30分钟)
|
# 令牌有效期(默认30分钟)
|
||||||
expireTime: 30
|
expireTime: 30
|
||||||
|
|
||||||
# MyBatis配置
|
# MyBatis Plus配置
|
||||||
mybatis:
|
mybatis-plus:
|
||||||
# 搜索指定包别名
|
# 搜索指定包别名
|
||||||
typeAliasesPackage: com.ruoyi.**.domain
|
typeAliasesPackage: com.ruoyi.**.domain
|
||||||
# 配置mapper的扫描,找到所有的mapper.xml映射文件
|
# 配置mapper的扫描,找到所有的mapper.xml映射文件
|
||||||
@@ -88,12 +80,14 @@ pagehelper:
|
|||||||
supportMethodsArguments: true
|
supportMethodsArguments: true
|
||||||
params: count=countSql
|
params: count=countSql
|
||||||
|
|
||||||
# Swagger配置
|
# Springdoc配置
|
||||||
swagger:
|
springdoc:
|
||||||
# 是否开启swagger
|
api-docs:
|
||||||
enabled: true
|
path: /v3/api-docs
|
||||||
# 请求前缀
|
swagger-ui:
|
||||||
pathMapping: /dev-api
|
enabled: true
|
||||||
|
path: /swagger-ui.html
|
||||||
|
tags-sorter: alpha
|
||||||
|
|
||||||
# 防盗链配置
|
# 防盗链配置
|
||||||
referer:
|
referer:
|
||||||
|
|||||||
1
ruoyi-admin/src/main/resources/license.dat
Executable file
1
ruoyi-admin/src/main/resources/license.dat
Executable file
@@ -0,0 +1 @@
|
|||||||
|
uc3Y29XJfVtZtZTbmF72t3V405cxamrXBnM0P0vqrrLnJjQ0T0Mt93avL/euwcmvgpWN09qZhbWX25eO9U91ptOrcWNK1XJz6z9waqNC5L40d09ybfrmrDP352Ny76fqyPauv06+ru7f+bTwG99zvHOS8bQvJub/rL3JkoKbfbnZXJmVyVtYwMjPTIjEyQtMsaWMQpnNlNlbkPTX2lTE5EwNsaWOApnNlNlb5cGX3RmVsU9czZQZWFmVhpjcfZGdGVT0yF0Z0LTMDITEwEyLuZFCmVXRl9kYxClPS01ByRXX1Y3b2RmFtRfTUb2ZT12Vi5nVXX1ClRnNpZlcfTnb25mVyVtYuMCPTclRX5FCQVVX0N1VO9DTKYmVD0GlwluZUV1PQpXJk9IYyZVd2FD0K9JZfTWVFd051F4XlcjbWJQpU0tMFZGV19W9ul0atYmPUVk5FVkCWRVV19U9OJTSJQ0X0x0U9VOQLWUWFlTU1lLbSMmSmhkNHlBRrcVdG8kNtUxYCT2RHFTc5lperM2WUFkkvU3M3MzTDBldOlqeTb3YUVGx3VWT1WkaERHhilxOTM0T0l1FrdBS1aUWG4GE5FtaLMyUXZUlz8zM0UnSCs0lDM5RDVFRzJDBzZmOoRkNFdEt6YwNKTkTXA1ZFVXXJT0UlNElD5fTDRTRU5TdU1YdROEL2xUhvV3OLY3bTVmhMpZUJU2QXF2I1VYdxTjWVVm9jZKUPWUMXFHNrFJeJZDU29mM2hKQpUmUVJGIxwwOVSUaXFXQy9JU4cFdlkGJQY4SCYWYjFkJndiaCVFMlNk1QZQTwQWRDJ0th1YMwaHYmEzQrB2aWTTRmpgpOA5dfVkRVd0lPVSUMSUTl9kNFNFTyaWPU0G5mNwaieUdUJ0NiZjNVbnOC90tNYyb2S3djNmh4BidmNlRnBk1PdCShdDYUdS9mNMSiMnYzVml2pSameEY2NStCZtRvU3dloGgvQyU0TmcTlTlMJVYhc3VEp01EpYRwUGNUUWZ5daVxU3blZzg3dnR2UncnR2U4RkU2CkSUc19W5FVTSURVJ0xJ9OXOQ0Q0VG1iU9WFcDYWNktah2M3blbjNlZsZndjOTdXFTFHNQS0SzUE4FVpdqR1dEL2RWgvpMSabVZkJlhRJFRMZUTUJ0NGdwUGbGZitjFE01bZSlRzZHZ4RMUFd2cHhEZqtZbwR2clQUgxFsb0Z1ZFVW5tJvUwWEd2gjVog1eKYUaUdHYK5JUXX1TkVlNJZFUfTET05U5DlDRTVURV9jJi49SmbHR2pU5UFwVUK0ZTBFE5pmd3ZGOEdXppU1VTNEb09UtntCRycUaHUmR1ovVYNGUU1HFy1vVsZXYlBmt1lsNVZDVUNUNyJQeHUXZlF2pzVMVlVjVmNWx2VxWZaUSEh1FlJ0bmRmbENkRV9VWiRVT3R01apMUIMkWjdW8K5JTXX1TkVlNJZFUfTET05U5DlDRTVURV9Ulw49bhMWcW5HdRdZNaK0UEp3AyU0TwY0Wm1md6tDMpN0cDRVBK11aKR0VTZkI3RocKUXRm5Vl6llcpMWaXJXRLZOOaZDOGZ1R0gychWURVJk5JR5VNYXQTl250dGYheFOG1FZog4RFZWMkRmtK1QRCaUclJlNYNFRHSWTFpFUKxYRXX1TkVlNJZFUfTET05U5DlDRTVURV9Hho49T5aTempVMwFhU1b1Vi9HR4YzO1dDNks05HhEQxY2VUZXlMNybyVmVEl3dNlLbYSGbGlWxMVNWUcEZXpVN0w5NVZDVGFUw4NMSUOWbkRjV21QaMbESVhGx1w3MiY1WmJXB6o0NjS1T2tWxjNSeRY0UzV0g2VhR5Z0RWlzkKRMdXX1TkVlNJZFUfTET05U5DlDRTVURV9Hdt49apUHZVNnhlpxQ5MENGNnh1VYN3aDQ2QW5qRqd4K1cXYk9ZdHW4VzeE9XVHB6YmM3Wk1DYwVLdqS1aTNUtjhINicVeUV1JBZRZxTGYWdTVytuepR1QVVXZlNoSVOFdVlVkzRqdPcjOW9HBll6Ota2dHFGV6dtN6c1ekN2UKdwc
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
window.onload = function() {
|
||||||
|
window.ui = SwaggerUIBundle({
|
||||||
|
url: "/v3/api-docs/default",
|
||||||
|
configUrl: "/v3/api-docs/swagger-config",
|
||||||
|
dom_id: '#swagger-ui',
|
||||||
|
deepLinking: true,
|
||||||
|
presets: [
|
||||||
|
SwaggerUIBundle.presets.apis,
|
||||||
|
SwaggerUIStandalonePreset
|
||||||
|
],
|
||||||
|
plugins: [
|
||||||
|
SwaggerUIBundle.plugins.DownloadUrl
|
||||||
|
],
|
||||||
|
layout: "StandaloneLayout",
|
||||||
|
tagsSorter: "alpha",
|
||||||
|
validatorUrl: "",
|
||||||
|
persistAuthorization: true
|
||||||
|
});
|
||||||
|
};
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
package com.ruoyi.web.controller.monitor;
|
||||||
|
|
||||||
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
|
||||||
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||||
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||||
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.test.web.servlet.MockMvc;
|
||||||
|
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||||
|
import com.ruoyi.common.core.cache.InMemoryCacheStore;
|
||||||
|
import com.ruoyi.common.core.redis.RedisCache;
|
||||||
|
|
||||||
|
class CacheControllerTest
|
||||||
|
{
|
||||||
|
@Test
|
||||||
|
void shouldReturnInMemoryCacheSummary() throws Exception
|
||||||
|
{
|
||||||
|
RedisCache redisCache = new RedisCache(new InMemoryCacheStore());
|
||||||
|
MockMvc mockMvc = MockMvcBuilders.standaloneSetup(new CacheController(redisCache)).build();
|
||||||
|
|
||||||
|
mockMvc.perform(get("/monitor/cache"))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$.data.info.cache_type").value("IN_MEMORY"))
|
||||||
|
.andExpect(jsonPath("$.data.info.cache_mode").value("single-instance"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldClearCacheKeysByPrefix() throws Exception
|
||||||
|
{
|
||||||
|
RedisCache redisCache = new RedisCache(new InMemoryCacheStore());
|
||||||
|
redisCache.setCacheObject("login_tokens:a", "A");
|
||||||
|
redisCache.setCacheObject("login_tokens:b", "B");
|
||||||
|
|
||||||
|
MockMvc mockMvc = MockMvcBuilders.standaloneSetup(new CacheController(redisCache)).build();
|
||||||
|
|
||||||
|
mockMvc.perform(delete("/monitor/cache/clearCacheName/login_tokens:"))
|
||||||
|
.andExpect(status().isOk());
|
||||||
|
|
||||||
|
mockMvc.perform(get("/monitor/cache/getKeys/login_tokens:"))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$.data").isEmpty());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package com.ruoyi.web.controller.system;
|
||||||
|
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||||
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.test.util.ReflectionTestUtils;
|
||||||
|
import org.springframework.test.web.servlet.MockMvc;
|
||||||
|
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||||
|
import com.ruoyi.framework.web.service.PasswordTransferCryptoService;
|
||||||
|
import com.ruoyi.framework.web.service.SysLoginService;
|
||||||
|
|
||||||
|
class SysLoginControllerPasswordTransferTest
|
||||||
|
{
|
||||||
|
@Test
|
||||||
|
void shouldDecryptPasswordBeforeCallingLoginService() throws Exception
|
||||||
|
{
|
||||||
|
SysLoginService loginService = mock(SysLoginService.class);
|
||||||
|
PasswordTransferCryptoService passwordTransferCryptoService = mock(PasswordTransferCryptoService.class);
|
||||||
|
when(passwordTransferCryptoService.decrypt("cipher")).thenReturn("admin123");
|
||||||
|
when(loginService.login("admin", "admin123", "1", "u")).thenReturn("token");
|
||||||
|
|
||||||
|
SysLoginController controller = new SysLoginController();
|
||||||
|
ReflectionTestUtils.setField(controller, "loginService", loginService);
|
||||||
|
ReflectionTestUtils.setField(controller, "passwordTransferCryptoService", passwordTransferCryptoService);
|
||||||
|
|
||||||
|
MockMvc mockMvc = MockMvcBuilders.standaloneSetup(controller).build();
|
||||||
|
|
||||||
|
mockMvc.perform(post("/login")
|
||||||
|
.contentType("application/json")
|
||||||
|
.content("{\"username\":\"admin\",\"password\":\"cipher\",\"code\":\"1\",\"uuid\":\"u\"}"))
|
||||||
|
.andExpect(status().isOk());
|
||||||
|
|
||||||
|
verify(passwordTransferCryptoService).decrypt("cipher");
|
||||||
|
verify(loginService).login("admin", "admin123", "1", "u");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
package com.ruoyi.web.controller.system;
|
||||||
|
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
|
||||||
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||||
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
|
import org.springframework.test.util.ReflectionTestUtils;
|
||||||
|
import org.springframework.test.web.servlet.MockMvc;
|
||||||
|
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||||
|
import com.ruoyi.common.core.domain.entity.SysUser;
|
||||||
|
import com.ruoyi.common.core.domain.model.LoginUser;
|
||||||
|
import com.ruoyi.common.utils.SecurityUtils;
|
||||||
|
import com.ruoyi.framework.web.service.PasswordTransferCryptoService;
|
||||||
|
import com.ruoyi.framework.web.service.TokenService;
|
||||||
|
import com.ruoyi.system.service.ISysUserService;
|
||||||
|
|
||||||
|
class SysProfileControllerPasswordTransferTest
|
||||||
|
{
|
||||||
|
@AfterEach
|
||||||
|
void tearDown()
|
||||||
|
{
|
||||||
|
SecurityContextHolder.clearContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldDecryptPasswordsBeforeCheckingOldPassword() throws Exception
|
||||||
|
{
|
||||||
|
ISysUserService userService = mock(ISysUserService.class);
|
||||||
|
TokenService tokenService = mock(TokenService.class);
|
||||||
|
PasswordTransferCryptoService passwordTransferCryptoService = mock(PasswordTransferCryptoService.class);
|
||||||
|
when(passwordTransferCryptoService.decrypt("oldCipher")).thenReturn("oldPlain");
|
||||||
|
when(passwordTransferCryptoService.decrypt("newCipher")).thenReturn("newPlain");
|
||||||
|
when(userService.resetUserPwd(org.mockito.ArgumentMatchers.anyLong(), org.mockito.ArgumentMatchers.anyString()))
|
||||||
|
.thenReturn(1);
|
||||||
|
|
||||||
|
SysUser storedUser = new SysUser();
|
||||||
|
storedUser.setUserId(2L);
|
||||||
|
storedUser.setPassword(SecurityUtils.encryptPassword("oldPlain"));
|
||||||
|
when(userService.selectUserById(2L)).thenReturn(storedUser);
|
||||||
|
|
||||||
|
SysUser currentUser = new SysUser();
|
||||||
|
currentUser.setUserId(2L);
|
||||||
|
currentUser.setUserName("admin");
|
||||||
|
LoginUser loginUser = new LoginUser(2L, 1L, currentUser, Collections.emptySet());
|
||||||
|
SecurityContextHolder.getContext()
|
||||||
|
.setAuthentication(new UsernamePasswordAuthenticationToken(loginUser, null, Collections.emptyList()));
|
||||||
|
|
||||||
|
SysProfileController controller = new SysProfileController();
|
||||||
|
ReflectionTestUtils.setField(controller, "userService", userService);
|
||||||
|
ReflectionTestUtils.setField(controller, "tokenService", tokenService);
|
||||||
|
ReflectionTestUtils.setField(controller, "passwordTransferCryptoService", passwordTransferCryptoService);
|
||||||
|
|
||||||
|
MockMvc mockMvc = MockMvcBuilders.standaloneSetup(controller).build();
|
||||||
|
|
||||||
|
mockMvc.perform(put("/system/user/profile/updatePwd")
|
||||||
|
.contentType("application/json")
|
||||||
|
.content("{\"oldPassword\":\"oldCipher\",\"newPassword\":\"newCipher\"}"))
|
||||||
|
.andExpect(status().isOk());
|
||||||
|
|
||||||
|
verify(passwordTransferCryptoService).decrypt("oldCipher");
|
||||||
|
verify(passwordTransferCryptoService).decrypt("newCipher");
|
||||||
|
verify(userService).resetUserPwd(org.mockito.ArgumentMatchers.eq(2L), org.mockito.ArgumentMatchers.anyString());
|
||||||
|
verify(tokenService).setLoginUser(loginUser);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
package com.ruoyi.web.controller.system;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||||
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.mockito.ArgumentCaptor;
|
||||||
|
import org.springframework.test.util.ReflectionTestUtils;
|
||||||
|
import org.springframework.test.web.servlet.MockMvc;
|
||||||
|
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||||
|
import com.ruoyi.common.core.domain.model.RegisterBody;
|
||||||
|
import com.ruoyi.framework.web.service.PasswordTransferCryptoService;
|
||||||
|
import com.ruoyi.framework.web.service.SysRegisterService;
|
||||||
|
import com.ruoyi.system.service.ISysConfigService;
|
||||||
|
|
||||||
|
class SysRegisterControllerPasswordTransferTest
|
||||||
|
{
|
||||||
|
@Test
|
||||||
|
void shouldDecryptPasswordBeforeCallingRegisterService() throws Exception
|
||||||
|
{
|
||||||
|
SysRegisterService registerService = mock(SysRegisterService.class);
|
||||||
|
ISysConfigService configService = mock(ISysConfigService.class);
|
||||||
|
PasswordTransferCryptoService passwordTransferCryptoService = mock(PasswordTransferCryptoService.class);
|
||||||
|
when(configService.selectConfigByKey("sys.account.registerUser")).thenReturn("true");
|
||||||
|
when(passwordTransferCryptoService.decrypt("cipher")).thenReturn("admin123");
|
||||||
|
when(registerService.register(any(RegisterBody.class))).thenReturn("");
|
||||||
|
|
||||||
|
SysRegisterController controller = new SysRegisterController();
|
||||||
|
ReflectionTestUtils.setField(controller, "registerService", registerService);
|
||||||
|
ReflectionTestUtils.setField(controller, "configService", configService);
|
||||||
|
ReflectionTestUtils.setField(controller, "passwordTransferCryptoService", passwordTransferCryptoService);
|
||||||
|
|
||||||
|
MockMvc mockMvc = MockMvcBuilders.standaloneSetup(controller).build();
|
||||||
|
|
||||||
|
mockMvc.perform(post("/register")
|
||||||
|
.contentType("application/json")
|
||||||
|
.content("{\"username\":\"u1\",\"password\":\"cipher\",\"code\":\"1\",\"uuid\":\"u\"}"))
|
||||||
|
.andExpect(status().isOk());
|
||||||
|
|
||||||
|
verify(passwordTransferCryptoService).decrypt("cipher");
|
||||||
|
ArgumentCaptor<RegisterBody> captor = ArgumentCaptor.forClass(RegisterBody.class);
|
||||||
|
verify(registerService).register(captor.capture());
|
||||||
|
assertEquals("admin123", captor.getValue().getPassword());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,113 @@
|
|||||||
|
package com.ruoyi.web.controller.system;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||||
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
|
||||||
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.mockito.ArgumentCaptor;
|
||||||
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||||
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
|
import org.springframework.test.util.ReflectionTestUtils;
|
||||||
|
import org.springframework.test.web.servlet.MockMvc;
|
||||||
|
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||||
|
import com.ruoyi.common.core.domain.entity.SysUser;
|
||||||
|
import com.ruoyi.common.core.domain.model.LoginUser;
|
||||||
|
import com.ruoyi.common.utils.SecurityUtils;
|
||||||
|
import com.ruoyi.framework.web.service.PasswordTransferCryptoService;
|
||||||
|
import com.ruoyi.system.service.ISysDeptService;
|
||||||
|
import com.ruoyi.system.service.ISysPostService;
|
||||||
|
import com.ruoyi.system.service.ISysRoleService;
|
||||||
|
import com.ruoyi.system.service.ISysUserService;
|
||||||
|
|
||||||
|
class SysUserControllerPasswordTransferTest
|
||||||
|
{
|
||||||
|
@AfterEach
|
||||||
|
void tearDown()
|
||||||
|
{
|
||||||
|
SecurityContextHolder.clearContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldDecryptPasswordBeforeAddingUser() throws Exception
|
||||||
|
{
|
||||||
|
ISysUserService userService = mock(ISysUserService.class);
|
||||||
|
ISysRoleService roleService = mock(ISysRoleService.class);
|
||||||
|
ISysDeptService deptService = mock(ISysDeptService.class);
|
||||||
|
ISysPostService postService = mock(ISysPostService.class);
|
||||||
|
PasswordTransferCryptoService passwordTransferCryptoService = mock(PasswordTransferCryptoService.class);
|
||||||
|
when(passwordTransferCryptoService.decrypt("cipher")).thenReturn("initPwd");
|
||||||
|
when(userService.checkUserNameUnique(org.mockito.ArgumentMatchers.any(SysUser.class))).thenReturn(true);
|
||||||
|
when(userService.insertUser(org.mockito.ArgumentMatchers.any(SysUser.class))).thenReturn(1);
|
||||||
|
|
||||||
|
setAuthentication();
|
||||||
|
|
||||||
|
SysUserController controller = new SysUserController();
|
||||||
|
ReflectionTestUtils.setField(controller, "userService", userService);
|
||||||
|
ReflectionTestUtils.setField(controller, "roleService", roleService);
|
||||||
|
ReflectionTestUtils.setField(controller, "deptService", deptService);
|
||||||
|
ReflectionTestUtils.setField(controller, "postService", postService);
|
||||||
|
ReflectionTestUtils.setField(controller, "passwordTransferCryptoService", passwordTransferCryptoService);
|
||||||
|
|
||||||
|
MockMvc mockMvc = MockMvcBuilders.standaloneSetup(controller).build();
|
||||||
|
|
||||||
|
mockMvc.perform(post("/system/user")
|
||||||
|
.contentType("application/json")
|
||||||
|
.content("{\"userName\":\"u1\",\"nickName\":\"n1\",\"deptId\":1,\"password\":\"cipher\"}"))
|
||||||
|
.andExpect(status().isOk());
|
||||||
|
|
||||||
|
verify(passwordTransferCryptoService).decrypt("cipher");
|
||||||
|
ArgumentCaptor<SysUser> captor = ArgumentCaptor.forClass(SysUser.class);
|
||||||
|
verify(userService).insertUser(captor.capture());
|
||||||
|
assertTrue(SecurityUtils.matchesPassword("initPwd", captor.getValue().getPassword()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldDecryptPasswordBeforeResettingUserPassword() throws Exception
|
||||||
|
{
|
||||||
|
ISysUserService userService = mock(ISysUserService.class);
|
||||||
|
ISysRoleService roleService = mock(ISysRoleService.class);
|
||||||
|
ISysDeptService deptService = mock(ISysDeptService.class);
|
||||||
|
ISysPostService postService = mock(ISysPostService.class);
|
||||||
|
PasswordTransferCryptoService passwordTransferCryptoService = mock(PasswordTransferCryptoService.class);
|
||||||
|
when(passwordTransferCryptoService.decrypt("cipher")).thenReturn("resetPwd");
|
||||||
|
when(userService.resetPwd(org.mockito.ArgumentMatchers.any(SysUser.class))).thenReturn(1);
|
||||||
|
|
||||||
|
setAuthentication();
|
||||||
|
|
||||||
|
SysUserController controller = new SysUserController();
|
||||||
|
ReflectionTestUtils.setField(controller, "userService", userService);
|
||||||
|
ReflectionTestUtils.setField(controller, "roleService", roleService);
|
||||||
|
ReflectionTestUtils.setField(controller, "deptService", deptService);
|
||||||
|
ReflectionTestUtils.setField(controller, "postService", postService);
|
||||||
|
ReflectionTestUtils.setField(controller, "passwordTransferCryptoService", passwordTransferCryptoService);
|
||||||
|
|
||||||
|
MockMvc mockMvc = MockMvcBuilders.standaloneSetup(controller).build();
|
||||||
|
|
||||||
|
mockMvc.perform(put("/system/user/resetPwd")
|
||||||
|
.contentType("application/json")
|
||||||
|
.content("{\"userId\":2,\"password\":\"cipher\"}"))
|
||||||
|
.andExpect(status().isOk());
|
||||||
|
|
||||||
|
verify(passwordTransferCryptoService).decrypt("cipher");
|
||||||
|
ArgumentCaptor<SysUser> captor = ArgumentCaptor.forClass(SysUser.class);
|
||||||
|
verify(userService).resetPwd(captor.capture());
|
||||||
|
assertTrue(SecurityUtils.matchesPassword("resetPwd", captor.getValue().getPassword()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setAuthentication()
|
||||||
|
{
|
||||||
|
SysUser currentUser = new SysUser();
|
||||||
|
currentUser.setUserId(1L);
|
||||||
|
currentUser.setUserName("admin");
|
||||||
|
LoginUser loginUser = new LoginUser(1L, 1L, currentUser, Collections.emptySet());
|
||||||
|
SecurityContextHolder.getContext()
|
||||||
|
.setAuthentication(new UsernamePasswordAuthenticationToken(loginUser, null, Collections.emptyList()));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>ruoyi</artifactId>
|
<artifactId>ruoyi</artifactId>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<version>3.9.2</version>
|
<version>3.9.1</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
@@ -89,18 +89,6 @@
|
|||||||
<artifactId>jaxb-api</artifactId>
|
<artifactId>jaxb-api</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- redis 缓存操作 -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-data-redis</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- pool 对象池 -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.commons</groupId>
|
|
||||||
<artifactId>commons-pool2</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- 解析客户端操作系统、浏览器等 -->
|
<!-- 解析客户端操作系统、浏览器等 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>nl.basjes.parse.useragent</groupId>
|
<groupId>nl.basjes.parse.useragent</groupId>
|
||||||
@@ -109,8 +97,32 @@
|
|||||||
|
|
||||||
<!-- servlet包 -->
|
<!-- servlet包 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>javax.servlet</groupId>
|
<groupId>jakarta.servlet</groupId>
|
||||||
<artifactId>javax.servlet-api</artifactId>
|
<artifactId>jakarta.servlet-api</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<!-- ruoyi-springboot3 / mybatis-plus 配置 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.mybatis</groupId>
|
||||||
|
<artifactId>mybatis</artifactId>
|
||||||
|
<version>3.5.16</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.baomidou</groupId>
|
||||||
|
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
|
||||||
|
<version>3.5.10</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.baomidou</groupId>
|
||||||
|
<artifactId>mybatis-plus-jsqlparser</artifactId>
|
||||||
|
<version>3.5.10</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|||||||
@@ -16,25 +16,15 @@ import java.lang.annotation.Target;
|
|||||||
@Documented
|
@Documented
|
||||||
public @interface DataScope
|
public @interface DataScope
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* 用户表的别名
|
|
||||||
*/
|
|
||||||
public String userAlias() default "";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 部门表的别名
|
* 部门表的别名
|
||||||
*/
|
*/
|
||||||
public String deptAlias() default "";
|
public String deptAlias() default "";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户字段名
|
* 用户表的别名
|
||||||
*/
|
*/
|
||||||
public String userField() default "user_id";
|
public String userAlias() default "";
|
||||||
|
|
||||||
/**
|
|
||||||
* 部门字段名
|
|
||||||
*/
|
|
||||||
public String deptField() default "dept_id";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 权限字符(用于多个角色匹配符合要求的权限)默认根据权限注解@ss获取,多个权限用逗号分隔开来
|
* 权限字符(用于多个角色匹配符合要求的权限)默认根据权限注解@ss获取,多个权限用逗号分隔开来
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ public @interface Excel
|
|||||||
/**
|
/**
|
||||||
* BigDecimal 舍入规则 默认:BigDecimal.ROUND_HALF_EVEN
|
* BigDecimal 舍入规则 默认:BigDecimal.ROUND_HALF_EVEN
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
public int roundingMode() default BigDecimal.ROUND_HALF_EVEN;
|
public int roundingMode() default BigDecimal.ROUND_HALF_EVEN;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -170,35 +170,4 @@ public class Constants
|
|||||||
*/
|
*/
|
||||||
public static final String[] JOB_ERROR_STR = { "java.net.URL", "javax.naming.InitialContext", "org.yaml.snakeyaml",
|
public static final String[] JOB_ERROR_STR = { "java.net.URL", "javax.naming.InitialContext", "org.yaml.snakeyaml",
|
||||||
"org.springframework", "org.apache", "com.ruoyi.common.utils.file", "com.ruoyi.common.config", "com.ruoyi.generator" };
|
"org.springframework", "org.apache", "com.ruoyi.common.utils.file", "com.ruoyi.common.config", "com.ruoyi.generator" };
|
||||||
|
|
||||||
/**
|
|
||||||
* 部门相关常量
|
|
||||||
*/
|
|
||||||
public static class Dept
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* 全部数据权限
|
|
||||||
*/
|
|
||||||
public static final String DATA_SCOPE_ALL = "1";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 自定数据权限
|
|
||||||
*/
|
|
||||||
public static final String DATA_SCOPE_CUSTOM = "2";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 部门数据权限
|
|
||||||
*/
|
|
||||||
public static final String DATA_SCOPE_DEPT = "3";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 部门及以下数据权限
|
|
||||||
*/
|
|
||||||
public static final String DATA_SCOPE_DEPT_AND_CHILD = "4";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 仅本人数据权限
|
|
||||||
*/
|
|
||||||
public static final String DATA_SCOPE_SELF = "5";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,9 +31,6 @@ public class GenConstants
|
|||||||
/** 上级菜单名称字段 */
|
/** 上级菜单名称字段 */
|
||||||
public static final String PARENT_MENU_NAME = "parentMenuName";
|
public static final String PARENT_MENU_NAME = "parentMenuName";
|
||||||
|
|
||||||
/** 生成详情页开关 */
|
|
||||||
public static final String GEN_VIEW = "genView";
|
|
||||||
|
|
||||||
/** 数据库字符串类型 */
|
/** 数据库字符串类型 */
|
||||||
public static final String[] COLUMNTYPE_STR = { "char", "varchar", "nvarchar", "varchar2" };
|
public static final String[] COLUMNTYPE_STR = { "char", "varchar", "nvarchar", "varchar2" };
|
||||||
|
|
||||||
|
|||||||
@@ -1,27 +1,8 @@
|
|||||||
package com.ruoyi.common.core.cache;
|
package com.ruoyi.common.core.cache;
|
||||||
|
|
||||||
public class InMemoryCacheEntry
|
record InMemoryCacheEntry(Object value, Long expireAtMillis)
|
||||||
{
|
{
|
||||||
private final Object value;
|
boolean isExpired(long now)
|
||||||
private final Long expireAtMillis;
|
|
||||||
|
|
||||||
public InMemoryCacheEntry(Object value, Long expireAtMillis)
|
|
||||||
{
|
|
||||||
this.value = value;
|
|
||||||
this.expireAtMillis = expireAtMillis;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object getValue()
|
|
||||||
{
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Long getExpireAtMillis()
|
|
||||||
{
|
|
||||||
return expireAtMillis;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isExpired(long now)
|
|
||||||
{
|
{
|
||||||
return expireAtMillis != null && expireAtMillis <= now;
|
return expireAtMillis != null && expireAtMillis <= now;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,58 +1,12 @@
|
|||||||
package com.ruoyi.common.core.cache;
|
package com.ruoyi.common.core.cache;
|
||||||
|
|
||||||
public class InMemoryCacheStats
|
public record InMemoryCacheStats(
|
||||||
|
String cacheType,
|
||||||
|
String mode,
|
||||||
|
long keySize,
|
||||||
|
long hitCount,
|
||||||
|
long missCount,
|
||||||
|
long expiredCount,
|
||||||
|
long writeCount)
|
||||||
{
|
{
|
||||||
private final String cacheType;
|
|
||||||
private final String mode;
|
|
||||||
private final long keySize;
|
|
||||||
private final long hitCount;
|
|
||||||
private final long missCount;
|
|
||||||
private final long expiredCount;
|
|
||||||
private final long writeCount;
|
|
||||||
|
|
||||||
public InMemoryCacheStats(String cacheType, String mode, long keySize, long hitCount, long missCount, long expiredCount, long writeCount)
|
|
||||||
{
|
|
||||||
this.cacheType = cacheType;
|
|
||||||
this.mode = mode;
|
|
||||||
this.keySize = keySize;
|
|
||||||
this.hitCount = hitCount;
|
|
||||||
this.missCount = missCount;
|
|
||||||
this.expiredCount = expiredCount;
|
|
||||||
this.writeCount = writeCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getCacheType()
|
|
||||||
{
|
|
||||||
return cacheType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getMode()
|
|
||||||
{
|
|
||||||
return mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getKeySize()
|
|
||||||
{
|
|
||||||
return keySize;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getHitCount()
|
|
||||||
{
|
|
||||||
return hitCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getMissCount()
|
|
||||||
{
|
|
||||||
return missCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getExpiredCount()
|
|
||||||
{
|
|
||||||
return expiredCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getWriteCount()
|
|
||||||
{
|
|
||||||
return writeCount;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,8 @@
|
|||||||
package com.ruoyi.common.core.cache;
|
package com.ruoyi.common.core.cache;
|
||||||
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@@ -14,6 +10,7 @@ import java.util.TreeSet;
|
|||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
public class InMemoryCacheStore
|
public class InMemoryCacheStore
|
||||||
@@ -39,7 +36,7 @@ public class InMemoryCacheStore
|
|||||||
public <T> T get(String key)
|
public <T> T get(String key)
|
||||||
{
|
{
|
||||||
InMemoryCacheEntry entry = readEntry(key);
|
InMemoryCacheEntry entry = readEntry(key);
|
||||||
return entry == null ? null : (T) entry.getValue();
|
return entry == null ? null : (T) entry.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasKey(String key)
|
public boolean hasKey(String key)
|
||||||
@@ -66,13 +63,12 @@ public class InMemoryCacheStore
|
|||||||
{
|
{
|
||||||
purgeExpiredEntries();
|
purgeExpiredEntries();
|
||||||
Set<String> matchedKeys = new TreeSet<>();
|
Set<String> matchedKeys = new TreeSet<>();
|
||||||
for (Map.Entry<String, InMemoryCacheEntry> entry : entries.entrySet())
|
entries.forEach((key, value) -> {
|
||||||
{
|
if (matches(pattern, key))
|
||||||
if (matches(pattern, entry.getKey()))
|
|
||||||
{
|
{
|
||||||
matchedKeys.add(entry.getKey());
|
matchedKeys.add(key);
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
return matchedKeys;
|
return matchedKeys;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,24 +76,9 @@ public class InMemoryCacheStore
|
|||||||
{
|
{
|
||||||
Objects.requireNonNull(unit, "TimeUnit must not be null");
|
Objects.requireNonNull(unit, "TimeUnit must not be null");
|
||||||
long expireAtMillis = System.currentTimeMillis() + Math.max(0L, unit.toMillis(timeout));
|
long expireAtMillis = System.currentTimeMillis() + Math.max(0L, unit.toMillis(timeout));
|
||||||
while (true)
|
return entries.computeIfPresent(key, (cacheKey, entry) -> entry.isExpired(System.currentTimeMillis())
|
||||||
{
|
? null
|
||||||
InMemoryCacheEntry currentEntry = entries.get(key);
|
: new InMemoryCacheEntry(entry.value(), expireAtMillis)) != null;
|
||||||
if (currentEntry == null)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (currentEntry.isExpired(System.currentTimeMillis()))
|
|
||||||
{
|
|
||||||
removeExpiredEntry(key, currentEntry);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
InMemoryCacheEntry nextEntry = new InMemoryCacheEntry(currentEntry.getValue(), expireAtMillis);
|
|
||||||
if (entries.replace(key, currentEntry, nextEntry))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getExpire(String key)
|
public long getExpire(String key)
|
||||||
@@ -112,11 +93,11 @@ public class InMemoryCacheStore
|
|||||||
{
|
{
|
||||||
return -2L;
|
return -2L;
|
||||||
}
|
}
|
||||||
if (entry.getExpireAtMillis() == null)
|
if (entry.expireAtMillis() == null)
|
||||||
{
|
{
|
||||||
return -1L;
|
return -1L;
|
||||||
}
|
}
|
||||||
long remainingMillis = Math.max(0L, entry.getExpireAtMillis() - System.currentTimeMillis());
|
long remainingMillis = Math.max(0L, entry.expireAtMillis() - System.currentTimeMillis());
|
||||||
long unitMillis = Math.max(1L, unit.toMillis(1));
|
long unitMillis = Math.max(1L, unit.toMillis(1));
|
||||||
return (remainingMillis + unitMillis - 1) / unitMillis;
|
return (remainingMillis + unitMillis - 1) / unitMillis;
|
||||||
}
|
}
|
||||||
@@ -128,10 +109,10 @@ public class InMemoryCacheStore
|
|||||||
entries.compute(key, (cacheKey, currentEntry) -> {
|
entries.compute(key, (cacheKey, currentEntry) -> {
|
||||||
long now = System.currentTimeMillis();
|
long now = System.currentTimeMillis();
|
||||||
boolean missingOrExpired = currentEntry == null || currentEntry.isExpired(now);
|
boolean missingOrExpired = currentEntry == null || currentEntry.isExpired(now);
|
||||||
long nextValue = missingOrExpired ? 1L : toLong(currentEntry.getValue()) + 1L;
|
long nextValue = missingOrExpired ? 1L : toLong(currentEntry.value()) + 1L;
|
||||||
Long expireAtMillis = (missingOrExpired || currentEntry.getExpireAtMillis() == null)
|
Long expireAtMillis = missingOrExpired || currentEntry.expireAtMillis() == null
|
||||||
? now + Math.max(0L, unit.toMillis(timeout))
|
? now + Math.max(0L, unit.toMillis(timeout))
|
||||||
: currentEntry.getExpireAtMillis();
|
: currentEntry.expireAtMillis();
|
||||||
if (missingOrExpired && currentEntry != null)
|
if (missingOrExpired && currentEntry != null)
|
||||||
{
|
{
|
||||||
expiredCount.incrementAndGet();
|
expiredCount.incrementAndGet();
|
||||||
@@ -161,7 +142,6 @@ public class InMemoryCacheStore
|
|||||||
writeCount.get());
|
writeCount.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public <T> Map<String, T> getMap(String key)
|
public <T> Map<String, T> getMap(String key)
|
||||||
{
|
{
|
||||||
Map<String, T> value = get(key);
|
Map<String, T> value = get(key);
|
||||||
@@ -198,7 +178,6 @@ public class InMemoryCacheStore
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public <T> Set<T> getSet(String key)
|
public <T> Set<T> getSet(String key)
|
||||||
{
|
{
|
||||||
Set<T> value = get(key);
|
Set<T> value = get(key);
|
||||||
@@ -210,28 +189,15 @@ public class InMemoryCacheStore
|
|||||||
set(key, new HashSet<>(dataSet));
|
set(key, new HashSet<>(dataSet));
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
public <T> java.util.List<T> getList(String key)
|
||||||
public <T> List<T> getList(String key)
|
|
||||||
{
|
{
|
||||||
List<T> value = get(key);
|
java.util.List<T> value = get(key);
|
||||||
return value == null ? null : new ArrayList<>(value);
|
return value == null ? null : new java.util.ArrayList<>(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T> void putList(String key, List<T> dataList)
|
public <T> void putList(String key, java.util.List<T> dataList)
|
||||||
{
|
{
|
||||||
set(key, new ArrayList<>(dataList));
|
set(key, new java.util.ArrayList<>(dataList));
|
||||||
}
|
|
||||||
|
|
||||||
private void setWithOptionalTtl(String key, Object value, long ttlMillis)
|
|
||||||
{
|
|
||||||
if (ttlMillis > 0)
|
|
||||||
{
|
|
||||||
set(key, value, ttlMillis, TimeUnit.MILLISECONDS);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
set(key, value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void putEntry(String key, InMemoryCacheEntry entry)
|
private void putEntry(String key, InMemoryCacheEntry entry)
|
||||||
@@ -261,13 +227,12 @@ public class InMemoryCacheStore
|
|||||||
private void purgeExpiredEntries()
|
private void purgeExpiredEntries()
|
||||||
{
|
{
|
||||||
long now = System.currentTimeMillis();
|
long now = System.currentTimeMillis();
|
||||||
for (Map.Entry<String, InMemoryCacheEntry> entry : entries.entrySet())
|
entries.forEach((key, entry) -> {
|
||||||
{
|
if (entry.isExpired(now))
|
||||||
if (entry.getValue().isExpired(now))
|
|
||||||
{
|
{
|
||||||
removeExpiredEntry(entry.getKey(), entry.getValue());
|
removeExpiredEntry(key, entry);
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void removeExpiredEntry(String key, InMemoryCacheEntry expectedEntry)
|
private void removeExpiredEntry(String key, InMemoryCacheEntry expectedEntry)
|
||||||
@@ -293,10 +258,20 @@ public class InMemoryCacheStore
|
|||||||
|
|
||||||
private long toLong(Object value)
|
private long toLong(Object value)
|
||||||
{
|
{
|
||||||
if (value instanceof Number)
|
if (value instanceof Number number)
|
||||||
{
|
{
|
||||||
return ((Number) value).longValue();
|
return number.longValue();
|
||||||
}
|
}
|
||||||
return Long.parseLong(String.valueOf(value));
|
return Long.parseLong(String.valueOf(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setWithOptionalTtl(String key, Object value, long ttlMillis)
|
||||||
|
{
|
||||||
|
if (ttlMillis > 0)
|
||||||
|
{
|
||||||
|
set(key, value, ttlMillis, TimeUnit.MILLISECONDS);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
set(key, value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,10 +2,10 @@ package com.ruoyi.common.core.domain.entity;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import javax.validation.constraints.Email;
|
import jakarta.validation.constraints.Email;
|
||||||
import javax.validation.constraints.NotBlank;
|
import jakarta.validation.constraints.NotBlank;
|
||||||
import javax.validation.constraints.NotNull;
|
import jakarta.validation.constraints.NotNull;
|
||||||
import javax.validation.constraints.Size;
|
import jakarta.validation.constraints.Size;
|
||||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||||
import com.ruoyi.common.core.domain.BaseEntity;
|
import com.ruoyi.common.core.domain.BaseEntity;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package com.ruoyi.common.core.domain.entity;
|
package com.ruoyi.common.core.domain.entity;
|
||||||
|
|
||||||
import javax.validation.constraints.NotBlank;
|
import jakarta.validation.constraints.NotBlank;
|
||||||
import javax.validation.constraints.Size;
|
import jakarta.validation.constraints.Size;
|
||||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||||
import com.ruoyi.common.annotation.Excel;
|
import com.ruoyi.common.annotation.Excel;
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
package com.ruoyi.common.core.domain.entity;
|
package com.ruoyi.common.core.domain.entity;
|
||||||
|
|
||||||
import javax.validation.constraints.NotBlank;
|
import jakarta.validation.constraints.NotBlank;
|
||||||
import javax.validation.constraints.Pattern;
|
import jakarta.validation.constraints.Pattern;
|
||||||
import javax.validation.constraints.Size;
|
import jakarta.validation.constraints.Size;
|
||||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||||
import com.ruoyi.common.annotation.Excel;
|
import com.ruoyi.common.annotation.Excel;
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ package com.ruoyi.common.core.domain.entity;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import javax.validation.constraints.NotBlank;
|
import jakarta.validation.constraints.NotBlank;
|
||||||
import javax.validation.constraints.NotNull;
|
import jakarta.validation.constraints.NotNull;
|
||||||
import javax.validation.constraints.Size;
|
import jakarta.validation.constraints.Size;
|
||||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||||
import com.ruoyi.common.core.domain.BaseEntity;
|
import com.ruoyi.common.core.domain.BaseEntity;
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
package com.ruoyi.common.core.domain.entity;
|
package com.ruoyi.common.core.domain.entity;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import javax.validation.constraints.NotBlank;
|
import jakarta.validation.constraints.NotBlank;
|
||||||
import javax.validation.constraints.NotNull;
|
import jakarta.validation.constraints.NotNull;
|
||||||
import javax.validation.constraints.Size;
|
import jakarta.validation.constraints.Size;
|
||||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||||
import com.ruoyi.common.annotation.Excel;
|
import com.ruoyi.common.annotation.Excel;
|
||||||
|
|||||||
@@ -2,10 +2,9 @@ package com.ruoyi.common.core.domain.entity;
|
|||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import javax.validation.constraints.*;
|
import jakarta.validation.constraints.*;
|
||||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
import com.ruoyi.common.annotation.Excel;
|
import com.ruoyi.common.annotation.Excel;
|
||||||
import com.ruoyi.common.annotation.Excel.ColumnType;
|
import com.ruoyi.common.annotation.Excel.ColumnType;
|
||||||
@@ -70,7 +69,6 @@ public class SysUser extends BaseEntity
|
|||||||
private String loginIp;
|
private String loginIp;
|
||||||
|
|
||||||
/** 最后登录时间 */
|
/** 最后登录时间 */
|
||||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
|
||||||
@Excel(name = "最后登录时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss", type = Type.EXPORT)
|
@Excel(name = "最后登录时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss", type = Type.EXPORT)
|
||||||
private Date loginDate;
|
private Date loginDate;
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,5 @@
|
|||||||
package com.ruoyi.common.core.redis;
|
package com.ruoyi.common.core.redis;
|
||||||
|
|
||||||
import com.ruoyi.common.core.cache.InMemoryCacheStats;
|
|
||||||
import com.ruoyi.common.core.cache.InMemoryCacheStore;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@@ -11,7 +7,15 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import com.ruoyi.common.core.cache.InMemoryCacheStats;
|
||||||
|
import com.ruoyi.common.core.cache.InMemoryCacheStore;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 本地缓存门面,保留原有 RedisCache 业务入口。
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
**/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Component
|
@Component
|
||||||
public class RedisCache
|
public class RedisCache
|
||||||
|
|||||||
@@ -3,14 +3,14 @@ package com.ruoyi.common.filter;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import javax.servlet.Filter;
|
import jakarta.servlet.Filter;
|
||||||
import javax.servlet.FilterChain;
|
import jakarta.servlet.FilterChain;
|
||||||
import javax.servlet.FilterConfig;
|
import jakarta.servlet.FilterConfig;
|
||||||
import javax.servlet.ServletException;
|
import jakarta.servlet.ServletException;
|
||||||
import javax.servlet.ServletRequest;
|
import jakarta.servlet.ServletRequest;
|
||||||
import javax.servlet.ServletResponse;
|
import jakarta.servlet.ServletResponse;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 防盗链过滤器
|
* 防盗链过滤器
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
package com.ruoyi.common.filter;
|
package com.ruoyi.common.filter;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import javax.servlet.Filter;
|
import jakarta.servlet.Filter;
|
||||||
import javax.servlet.FilterChain;
|
import jakarta.servlet.FilterChain;
|
||||||
import javax.servlet.FilterConfig;
|
import jakarta.servlet.FilterConfig;
|
||||||
import javax.servlet.ServletException;
|
import jakarta.servlet.ServletException;
|
||||||
import javax.servlet.ServletRequest;
|
import jakarta.servlet.ServletRequest;
|
||||||
import javax.servlet.ServletResponse;
|
import jakarta.servlet.ServletResponse;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
|
|
||||||
|
|||||||
@@ -4,11 +4,11 @@ import java.io.BufferedReader;
|
|||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import javax.servlet.ReadListener;
|
import jakarta.servlet.ReadListener;
|
||||||
import javax.servlet.ServletInputStream;
|
import jakarta.servlet.ServletInputStream;
|
||||||
import javax.servlet.ServletResponse;
|
import jakarta.servlet.ServletResponse;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletRequestWrapper;
|
import jakarta.servlet.http.HttpServletRequestWrapper;
|
||||||
import com.ruoyi.common.utils.http.HttpHelper;
|
import com.ruoyi.common.utils.http.HttpHelper;
|
||||||
import com.ruoyi.common.constant.Constants;
|
import com.ruoyi.common.constant.Constants;
|
||||||
|
|
||||||
|
|||||||
@@ -3,14 +3,14 @@ package com.ruoyi.common.filter;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import javax.servlet.Filter;
|
import jakarta.servlet.Filter;
|
||||||
import javax.servlet.FilterChain;
|
import jakarta.servlet.FilterChain;
|
||||||
import javax.servlet.FilterConfig;
|
import jakarta.servlet.FilterConfig;
|
||||||
import javax.servlet.ServletException;
|
import jakarta.servlet.ServletException;
|
||||||
import javax.servlet.ServletRequest;
|
import jakarta.servlet.ServletRequest;
|
||||||
import javax.servlet.ServletResponse;
|
import jakarta.servlet.ServletResponse;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
import com.ruoyi.common.enums.HttpMethod;
|
import com.ruoyi.common.enums.HttpMethod;
|
||||||
|
|
||||||
|
|||||||
@@ -2,10 +2,10 @@ package com.ruoyi.common.filter;
|
|||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import javax.servlet.ReadListener;
|
import jakarta.servlet.ReadListener;
|
||||||
import javax.servlet.ServletInputStream;
|
import jakarta.servlet.ServletInputStream;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletRequestWrapper;
|
import jakarta.servlet.http.HttpServletRequestWrapper;
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.HttpHeaders;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import org.apache.commons.lang3.time.DateFormatUtils;
|
|||||||
*
|
*
|
||||||
* @author ruoyi
|
* @author ruoyi
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
public class DateUtils extends org.apache.commons.lang3.time.DateUtils
|
public class DateUtils extends org.apache.commons.lang3.time.DateUtils
|
||||||
{
|
{
|
||||||
public static String YYYY = "yyyy";
|
public static String YYYY = "yyyy";
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import java.util.Collection;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import com.alibaba.fastjson2.JSONArray;
|
import com.alibaba.fastjson2.JSON;
|
||||||
import com.ruoyi.common.constant.CacheConstants;
|
import com.ruoyi.common.constant.CacheConstants;
|
||||||
import com.ruoyi.common.core.domain.entity.SysDictData;
|
import com.ruoyi.common.core.domain.entity.SysDictData;
|
||||||
import com.ruoyi.common.core.redis.RedisCache;
|
import com.ruoyi.common.core.redis.RedisCache;
|
||||||
@@ -41,10 +41,14 @@ public class DictUtils
|
|||||||
*/
|
*/
|
||||||
public static List<SysDictData> getDictCache(String key)
|
public static List<SysDictData> getDictCache(String key)
|
||||||
{
|
{
|
||||||
JSONArray arrayCache = SpringUtils.getBean(RedisCache.class).getCacheObject(getCacheKey(key));
|
Object cacheObject = SpringUtils.getBean(RedisCache.class).getCacheObject(getCacheKey(key));
|
||||||
if (StringUtils.isNotNull(arrayCache))
|
if (cacheObject instanceof List<?> listCache)
|
||||||
{
|
{
|
||||||
return arrayCache.toList(SysDictData.class);
|
return (List<SysDictData>) listCache;
|
||||||
|
}
|
||||||
|
if (StringUtils.isNotNull(cacheObject))
|
||||||
|
{
|
||||||
|
return JSON.parseArray(JSON.toJSONString(cacheObject), SysDictData.class);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,10 +7,10 @@ import java.net.URLEncoder;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import javax.servlet.ServletRequest;
|
import jakarta.servlet.ServletRequest;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import javax.servlet.http.HttpSession;
|
import jakarta.servlet.http.HttpSession;
|
||||||
import org.springframework.web.context.request.RequestAttributes;
|
import org.springframework.web.context.request.RequestAttributes;
|
||||||
import org.springframework.web.context.request.RequestContextHolder;
|
import org.springframework.web.context.request.RequestContextHolder;
|
||||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import com.ruoyi.common.core.text.StrFormatter;
|
|||||||
*
|
*
|
||||||
* @author ruoyi
|
* @author ruoyi
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
public class StringUtils extends org.apache.commons.lang3.StringUtils
|
public class StringUtils extends org.apache.commons.lang3.StringUtils
|
||||||
{
|
{
|
||||||
/** 空字符串 */
|
/** 空字符串 */
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
package com.ruoyi.common.utils.bean;
|
package com.ruoyi.common.utils.bean;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import javax.validation.ConstraintViolation;
|
import jakarta.validation.ConstraintViolation;
|
||||||
import javax.validation.ConstraintViolationException;
|
import jakarta.validation.ConstraintViolationException;
|
||||||
import javax.validation.Validator;
|
import jakarta.validation.Validator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* bean对象属性验证
|
* bean对象属性验证
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ import java.io.OutputStream;
|
|||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import org.apache.commons.io.FilenameUtils;
|
import org.apache.commons.io.FilenameUtils;
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.apache.commons.lang3.ArrayUtils;
|
import org.apache.commons.lang3.ArrayUtils;
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import java.io.IOException;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import javax.servlet.ServletRequest;
|
import jakarta.servlet.ServletRequest;
|
||||||
import org.apache.commons.lang3.exception.ExceptionUtils;
|
import org.apache.commons.lang3.exception.ExceptionUtils;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ import java.net.URL;
|
|||||||
import java.net.URLConnection;
|
import java.net.URLConnection;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Map;
|
||||||
import javax.net.ssl.HostnameVerifier;
|
import javax.net.ssl.HostnameVerifier;
|
||||||
import javax.net.ssl.HttpsURLConnection;
|
import javax.net.ssl.HttpsURLConnection;
|
||||||
import javax.net.ssl.SSLContext;
|
import javax.net.ssl.SSLContext;
|
||||||
@@ -21,7 +23,10 @@ import org.slf4j.Logger;
|
|||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import com.ruoyi.common.constant.Constants;
|
import com.ruoyi.common.constant.Constants;
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.*;
|
||||||
|
import org.springframework.util.LinkedMultiValueMap;
|
||||||
|
import org.springframework.util.MultiValueMap;
|
||||||
|
import org.springframework.web.client.RestTemplate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通用http发送方法
|
* 通用http发送方法
|
||||||
@@ -290,4 +295,79 @@ public class HttpUtils
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送 POST 请求(application/x-www-form-urlencoded 格式)
|
||||||
|
* @param url 请求地址
|
||||||
|
* @param params 表单参数
|
||||||
|
* @param headers 请求头(可为 null)
|
||||||
|
* @param responseType 响应类型
|
||||||
|
* @param <T> 泛型返回值
|
||||||
|
* @return 响应结果
|
||||||
|
*/
|
||||||
|
public static <T> T doPostFormUrlEncoded(String url, Map<String, String> params, HttpHeaders headers, Class<T> responseType) {
|
||||||
|
// 构建表单参数
|
||||||
|
MultiValueMap<String, String> formParams = new LinkedMultiValueMap<>();
|
||||||
|
if (params != null && !params.isEmpty()) {
|
||||||
|
formParams.setAll(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构建请求头(指定 Content-Type)
|
||||||
|
HttpHeaders requestHeaders = headers == null ? new HttpHeaders() : headers;
|
||||||
|
requestHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
|
||||||
|
requestHeaders.setAcceptCharset(Collections.singletonList(StandardCharsets.UTF_8));
|
||||||
|
|
||||||
|
HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(formParams, requestHeaders);
|
||||||
|
RestTemplate restTemplate = new RestTemplate();
|
||||||
|
// 发送请求
|
||||||
|
try {
|
||||||
|
ResponseEntity<T> response = restTemplate.exchange(
|
||||||
|
url,
|
||||||
|
HttpMethod.POST,
|
||||||
|
requestEntity,
|
||||||
|
responseType
|
||||||
|
);
|
||||||
|
log.info("---------------------->POST(form-urlencoded) 请求成功,URL:{},响应结果:{}", url, response.getBody());
|
||||||
|
return response.getBody();
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("POST(form-urlencoded) 请求失败,URL:" + url + ",异常信息:" + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== 新增:JSON 格式 POST 请求 ==========
|
||||||
|
/**
|
||||||
|
* 发送 POST 请求(application/json 格式)
|
||||||
|
* @param url 请求地址
|
||||||
|
* @param requestBody 请求体(Java 对象,自动序列化为 JSON)
|
||||||
|
* @param headers 请求头(可为 null,默认已设置 Content-Type: application/json)
|
||||||
|
* @param responseType 响应类型
|
||||||
|
* @param <T> 响应泛型类型
|
||||||
|
* @param <R> 请求体类型
|
||||||
|
* @return 响应结果
|
||||||
|
*/
|
||||||
|
public static <T, R> T doPostJson(String url, R requestBody, HttpHeaders headers, Class<T> responseType) {
|
||||||
|
// 构建请求头,默认设置 JSON 格式
|
||||||
|
HttpHeaders requestHeaders = headers == null ? new HttpHeaders() : headers;
|
||||||
|
// 确保 Content-Type 为 JSON,避免外部传入覆盖
|
||||||
|
if (!requestHeaders.containsKey(HttpHeaders.CONTENT_TYPE)) {
|
||||||
|
requestHeaders.setContentType(MediaType.APPLICATION_JSON_UTF8);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构建请求实体(请求体 + 请求头)
|
||||||
|
HttpEntity<R> requestEntity = new HttpEntity<>(requestBody, requestHeaders);
|
||||||
|
RestTemplate restTemplate = new RestTemplate();
|
||||||
|
// 发送 JSON POST 请求
|
||||||
|
try {
|
||||||
|
ResponseEntity<T> response = restTemplate.exchange(
|
||||||
|
url,
|
||||||
|
HttpMethod.POST,
|
||||||
|
requestEntity,
|
||||||
|
responseType
|
||||||
|
);
|
||||||
|
log.info("---------------------->POST(JSON) 请求成功,URL:{},响应结果:{}", url, response.getBody());
|
||||||
|
return response.getBody();
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("POST(JSON) 请求失败,URL:" + url + ",异常信息:" + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -19,7 +19,7 @@ public class AddressUtils
|
|||||||
private static final Logger log = LoggerFactory.getLogger(AddressUtils.class);
|
private static final Logger log = LoggerFactory.getLogger(AddressUtils.class);
|
||||||
|
|
||||||
// IP地址查询
|
// IP地址查询
|
||||||
public static final String IP_URL = "https://whois.pconline.com.cn/ipJson.jsp";
|
public static final String IP_URL = "http://whois.pconline.com.cn/ipJson.jsp";
|
||||||
|
|
||||||
// 未知地址
|
// 未知地址
|
||||||
public static final String UNKNOWN = "XX XX";
|
public static final String UNKNOWN = "XX XX";
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package com.ruoyi.common.utils.ip;
|
|||||||
|
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import com.ruoyi.common.utils.ServletUtils;
|
import com.ruoyi.common.utils.ServletUtils;
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
|
|
||||||
|
|||||||
@@ -1,85 +0,0 @@
|
|||||||
package com.ruoyi.common.utils.poi;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 多 Sheet 导出时的数据信息
|
|
||||||
*
|
|
||||||
* 使用示例:
|
|
||||||
* <pre>
|
|
||||||
* List<ExcelSheet<?>> sheets = new ArrayList<>();
|
|
||||||
* sheets.add(new ExcelSheet<>("参数数据", configList, Config.class, "参数信息"));
|
|
||||||
* sheets.add(new ExcelSheet<>("岗位数据", postList, Post.class, "岗位信息"));
|
|
||||||
* return ExcelUtil.exportMultiSheet(sheets);
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
*/
|
|
||||||
public class ExcelSheet<T>
|
|
||||||
{
|
|
||||||
/** Sheet 名称 */
|
|
||||||
private String sheetName;
|
|
||||||
|
|
||||||
/** 导出数据集合 */
|
|
||||||
private List<T> list;
|
|
||||||
|
|
||||||
/** 数据对应的实体 Class */
|
|
||||||
private Class<T> clazz;
|
|
||||||
|
|
||||||
/** Sheet 顶部大标题(可为空) */
|
|
||||||
private String title;
|
|
||||||
|
|
||||||
public ExcelSheet(String sheetName, List<T> list, Class<T> clazz)
|
|
||||||
{
|
|
||||||
this(sheetName, list, clazz, "");
|
|
||||||
}
|
|
||||||
|
|
||||||
public ExcelSheet(String sheetName, List<T> list, Class<T> clazz, String title)
|
|
||||||
{
|
|
||||||
this.sheetName = sheetName;
|
|
||||||
this.list = list != null ? list : new ArrayList<>();
|
|
||||||
this.clazz = clazz;
|
|
||||||
this.title = title != null ? title : "";
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getSheetName()
|
|
||||||
{
|
|
||||||
return sheetName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<T> getList()
|
|
||||||
{
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Class<T> getClazz()
|
|
||||||
{
|
|
||||||
return clazz;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getTitle()
|
|
||||||
{
|
|
||||||
return title;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSheetName(String sheetName)
|
|
||||||
{
|
|
||||||
this.sheetName = sheetName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setList(List<T> list)
|
|
||||||
{
|
|
||||||
this.list = list;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setClazz(Class<T> clazz)
|
|
||||||
{
|
|
||||||
this.clazz = clazz;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTitle(String title)
|
|
||||||
{
|
|
||||||
this.title = title;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -23,7 +23,7 @@ import java.util.Map;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import org.apache.commons.lang3.ArrayUtils;
|
import org.apache.commons.lang3.ArrayUtils;
|
||||||
import org.apache.commons.lang3.RegExUtils;
|
import org.apache.commons.lang3.RegExUtils;
|
||||||
import org.apache.commons.lang3.reflect.FieldUtils;
|
import org.apache.commons.lang3.reflect.FieldUtils;
|
||||||
@@ -106,11 +106,6 @@ public class ExcelUtil<T>
|
|||||||
*/
|
*/
|
||||||
public Map<String, String> sysDictMap = new HashMap<String, String>();
|
public Map<String, String> sysDictMap = new HashMap<String, String>();
|
||||||
|
|
||||||
/**
|
|
||||||
* 单元格样式缓存
|
|
||||||
*/
|
|
||||||
private Map<String, CellStyle> cellStyleCache = new HashMap<String, CellStyle>();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Excel sheet最大行数,默认65536
|
* Excel sheet最大行数,默认65536
|
||||||
*/
|
*/
|
||||||
@@ -423,7 +418,7 @@ public class ExcelUtil<T>
|
|||||||
Object val = this.getCellValue(row, entry.getKey());
|
Object val = this.getCellValue(row, entry.getKey());
|
||||||
|
|
||||||
// 如果不存在实例则新建.
|
// 如果不存在实例则新建.
|
||||||
entity = (entity == null ? clazz.newInstance() : entity);
|
entity = (entity == null ? clazz.getDeclaredConstructor().newInstance() : entity);
|
||||||
// 从map中得到对应列的field.
|
// 从map中得到对应列的field.
|
||||||
Field field = (Field) entry.getValue()[0];
|
Field field = (Field) entry.getValue()[0];
|
||||||
Excel attr = (Excel) entry.getValue()[1];
|
Excel attr = (Excel) entry.getValue()[1];
|
||||||
@@ -585,117 +580,6 @@ public class ExcelUtil<T>
|
|||||||
exportExcel(response);
|
exportExcel(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 多 Sheet 导出 —— 将多个不同类型的数据集合写入同一 Excel,直接输出到 HttpServletResponse
|
|
||||||
*
|
|
||||||
* @param response HTTP 响应
|
|
||||||
* @param sheets Sheet 描述列表
|
|
||||||
*/
|
|
||||||
public static void exportMultiSheet(HttpServletResponse response, List<ExcelSheet<?>> sheets)
|
|
||||||
{
|
|
||||||
if (sheets == null || sheets.isEmpty())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
SXSSFWorkbook wb = buildWorkbook(sheets);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
|
||||||
response.setCharacterEncoding("utf-8");
|
|
||||||
wb.write(response.getOutputStream());
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
log.error("多Sheet导出Excel异常{}", e.getMessage());
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
IOUtils.closeQuietly(wb);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 多 Sheet 导出 —— 将多个不同类型的数据集合写入同一 Excel,生成文件并返回下载地址
|
|
||||||
*
|
|
||||||
* @param sheets Sheet 描述列表
|
|
||||||
* @return AjaxResult(含文件下载地址)
|
|
||||||
*/
|
|
||||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
|
||||||
public static AjaxResult exportMultiSheet(List<ExcelSheet<?>> sheets)
|
|
||||||
{
|
|
||||||
if (sheets == null || sheets.isEmpty())
|
|
||||||
{
|
|
||||||
return AjaxResult.error("导出数据不能为空");
|
|
||||||
}
|
|
||||||
SXSSFWorkbook wb = buildWorkbook(sheets);
|
|
||||||
OutputStream out = null;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
ExcelUtil firstUtil = new ExcelUtil(sheets.get(0).getClazz());
|
|
||||||
String filename = firstUtil.encodingFilename(sheets.get(0).getSheetName());
|
|
||||||
out = new FileOutputStream(firstUtil.getAbsoluteFile(filename));
|
|
||||||
wb.write(out);
|
|
||||||
return AjaxResult.success(filename);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
log.error("多Sheet导出Excel异常{}", e.getMessage());
|
|
||||||
throw new UtilException("导出Excel失败,请联系网站管理员!");
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
IOUtils.closeQuietly(wb);
|
|
||||||
IOUtils.closeQuietly(out);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 构建多 Sheet Workbook —— 创建 SXSSFWorkbook 并将所有 Sheet 数据写入
|
|
||||||
*
|
|
||||||
* @param sheets Sheet 描述列表
|
|
||||||
* @return 已写入所有 Sheet 数据的 SXSSFWorkbook
|
|
||||||
*/
|
|
||||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
|
||||||
private static SXSSFWorkbook buildWorkbook(List<ExcelSheet<?>> sheets)
|
|
||||||
{
|
|
||||||
SXSSFWorkbook wb = new SXSSFWorkbook(500);
|
|
||||||
for (ExcelSheet<?> excelSheet : sheets)
|
|
||||||
{
|
|
||||||
ExcelUtil util = new ExcelUtil(excelSheet.getClazz());
|
|
||||||
util.initWithWorkbook(wb, excelSheet.getList(), excelSheet.getSheetName(), excelSheet.getTitle());
|
|
||||||
util.writeSheet();
|
|
||||||
}
|
|
||||||
return wb;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 使用外部传入的 Workbook 初始化(多 Sheet 导出专用)
|
|
||||||
* 与 init() 的区别:不新建 Workbook,而是在已有 wb 上追加新 Sheet
|
|
||||||
*
|
|
||||||
* @param wb 已有工作簿
|
|
||||||
* @param list 数据集合
|
|
||||||
* @param sheetName Sheet 名称
|
|
||||||
* @param title 大标题(可为空)
|
|
||||||
*/
|
|
||||||
public void initWithWorkbook(SXSSFWorkbook wb, List<T> list, String sheetName, String title)
|
|
||||||
{
|
|
||||||
if (list == null)
|
|
||||||
{
|
|
||||||
list = new ArrayList<T>();
|
|
||||||
}
|
|
||||||
this.list = list;
|
|
||||||
this.sheetName = sheetName;
|
|
||||||
this.title = title != null ? title : "";
|
|
||||||
this.type = Type.EXPORT;
|
|
||||||
this.rownum = 0;
|
|
||||||
this.wb = wb;
|
|
||||||
this.sheet = wb.createSheet(sheetName);
|
|
||||||
createExcelField();
|
|
||||||
this.styles = createStyles(wb);
|
|
||||||
createTitle();
|
|
||||||
createSubHead();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 对list数据源将其里面的数据导入到excel表单
|
* 对list数据源将其里面的数据导入到excel表单
|
||||||
*
|
*
|
||||||
@@ -1240,7 +1124,8 @@ public class ExcelUtil<T>
|
|||||||
/**
|
/**
|
||||||
* 添加单元格
|
* 添加单元格
|
||||||
*/
|
*/
|
||||||
public Cell addCell(Excel attr, Row row, T vo, Field field, int column)
|
@SuppressWarnings("deprecation")
|
||||||
|
public Cell addCell(Excel attr, Row row, T vo, Field field, int column)
|
||||||
{
|
{
|
||||||
Cell cell = null;
|
Cell cell = null;
|
||||||
try
|
try
|
||||||
@@ -1317,16 +1202,9 @@ public class ExcelUtil<T>
|
|||||||
*/
|
*/
|
||||||
private CellStyle createCellStyle(CellStyle cellStyle, String format)
|
private CellStyle createCellStyle(CellStyle cellStyle, String format)
|
||||||
{
|
{
|
||||||
String key = cellStyle.getIndex() + "|" + format;
|
|
||||||
CellStyle cached = cellStyleCache.get(key);
|
|
||||||
if (cached != null)
|
|
||||||
{
|
|
||||||
return cached;
|
|
||||||
}
|
|
||||||
CellStyle style = wb.createCellStyle();
|
CellStyle style = wb.createCellStyle();
|
||||||
style.cloneStyleFrom(cellStyle);
|
style.cloneStyleFrom(cellStyle);
|
||||||
style.setDataFormat(wb.getCreationHelper().createDataFormat().getFormat(format));
|
style.setDataFormat(wb.getCreationHelper().createDataFormat().getFormat(format));
|
||||||
cellStyleCache.put(key, style);
|
|
||||||
return style;
|
return style;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1548,7 +1426,7 @@ public class ExcelUtil<T>
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Object instance = excel.handler().newInstance();
|
Object instance = excel.handler().getDeclaredConstructor().newInstance();
|
||||||
Method formatMethod = excel.handler().getMethod("format", new Class[] { Object.class, String[].class, Cell.class, Workbook.class });
|
Method formatMethod = excel.handler().getMethod("format", new Class[] { Object.class, String[].class, Cell.class, Workbook.class });
|
||||||
value = formatMethod.invoke(instance, value, excel.args(), cell, this.wb);
|
value = formatMethod.invoke(instance, value, excel.args(), cell, this.wb);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -310,6 +310,7 @@ public class ReflectUtils
|
|||||||
/**
|
/**
|
||||||
* 改变private/protected的方法为public,尽量不调用实际改动的语句,避免JDK的SecurityManager抱怨。
|
* 改变private/protected的方法为public,尽量不调用实际改动的语句,避免JDK的SecurityManager抱怨。
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
public static void makeAccessible(Method method)
|
public static void makeAccessible(Method method)
|
||||||
{
|
{
|
||||||
if ((!Modifier.isPublic(method.getModifiers()) || !Modifier.isPublic(method.getDeclaringClass().getModifiers()))
|
if ((!Modifier.isPublic(method.getModifiers()) || !Modifier.isPublic(method.getDeclaringClass().getModifiers()))
|
||||||
@@ -322,6 +323,7 @@ public class ReflectUtils
|
|||||||
/**
|
/**
|
||||||
* 改变private/protected的成员变量为public,尽量不调用实际改动的语句,避免JDK的SecurityManager抱怨。
|
* 改变private/protected的成员变量为public,尽量不调用实际改动的语句,避免JDK的SecurityManager抱怨。
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
public static void makeAccessible(Field field)
|
public static void makeAccessible(Field field)
|
||||||
{
|
{
|
||||||
if ((!Modifier.isPublic(field.getModifiers()) || !Modifier.isPublic(field.getDeclaringClass().getModifiers())
|
if ((!Modifier.isPublic(field.getModifiers()) || !Modifier.isPublic(field.getDeclaringClass().getModifiers())
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ public class SqlUtil
|
|||||||
/**
|
/**
|
||||||
* 定义常用的 sql关键字
|
* 定义常用的 sql关键字
|
||||||
*/
|
*/
|
||||||
public static String SQL_REGEX = "\u000B|%0A|and |extractvalue|updatexml|sleep|information_schema|exec |insert |select |delete |update |drop |count |chr |mid |master |truncate |char |declare |or |union |like |+|/*|user()";
|
public static String SQL_REGEX = "\u000B|and |extractvalue|updatexml|sleep|information_schema|exec |insert |select |delete |update |drop |count |chr |mid |master |truncate |char |declare |or |union |like |+|/*|user()";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 仅支持字母、数字、下划线、空格、逗号、小数点(支持多个字段排序)
|
* 仅支持字母、数字、下划线、空格、逗号、小数点(支持多个字段排序)
|
||||||
@@ -58,13 +58,12 @@ public class SqlUtil
|
|||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
String normalizedValue = value.replaceAll("\\p{Z}|\\s", "");
|
|
||||||
String[] sqlKeywords = StringUtils.split(SQL_REGEX, "\\|");
|
String[] sqlKeywords = StringUtils.split(SQL_REGEX, "\\|");
|
||||||
for (String sqlKeyword : sqlKeywords)
|
for (String sqlKeyword : sqlKeywords)
|
||||||
{
|
{
|
||||||
if (StringUtils.indexOfIgnoreCase(normalizedValue, sqlKeyword) > -1)
|
if (StringUtils.indexOfIgnoreCase(value, sqlKeyword) > -1)
|
||||||
{
|
{
|
||||||
throw new UtilException("请求参数包含敏感关键词'" + sqlKeyword + "',可能存在安全风险");
|
throw new UtilException("参数存在SQL注入风险");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package com.ruoyi.common.xss;
|
package com.ruoyi.common.xss;
|
||||||
|
|
||||||
import javax.validation.Constraint;
|
import jakarta.validation.Constraint;
|
||||||
import javax.validation.Payload;
|
import jakarta.validation.Payload;
|
||||||
import java.lang.annotation.ElementType;
|
import java.lang.annotation.ElementType;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
package com.ruoyi.common.xss;
|
package com.ruoyi.common.xss;
|
||||||
|
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
import javax.validation.ConstraintValidator;
|
import jakarta.validation.ConstraintValidator;
|
||||||
import javax.validation.ConstraintValidatorContext;
|
import jakarta.validation.ConstraintValidatorContext;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user