4 Commits

Author SHA1 Message Date
wkc
28088d43a8 迁移项目到 RuoYi-Vue springboot2 基线 2026-04-14 15:13:51 +08:00
wkc
f1e4b26800 调整个人最终测算利率展示并重排详情卡片 2026-04-11 15:33:40 +08:00
wkc
235672304a delete 2026-04-11 15:02:57 +08:00
wkc
ec4a7c09db delete 2026-04-10 15:21:45 +08:00
554 changed files with 73890 additions and 70436 deletions

View File

@@ -1,5 +0,0 @@
{
"permissions": {
"allow": []
}
}

View File

@@ -1,30 +0,0 @@
{
"permissions": {
"allow": [
"Bash(java:*)",
"Bash(binrun.bat:*)",
"Bash(mvn clean package:*)",
"Bash(curl:*)",
"Bash(pkill:*)",
"Bash(bash:*)",
"Bash(pip install:*)",
"Bash(findstr:*)",
"Bash(chcp:*)",
"Bash(cmd.exe:*)",
"Bash(powershell -Command:*)",
"Bash(git add:*)",
"Bash(cd:*)",
"mcp__zai-mcp-server__extract_text_from_screenshot",
"Bash(mvn test:*)",
"Bash(mvn install:*)",
"Bash(mvn clean install:*)",
"mcp__web-reader__webReader",
"Skill(superpowers:brainstorming)",
"Skill(superpowers:writing-plans)",
"Skill(superpowers:executing-plans)"
],
"additionalDirectories": [
"d:\\利率定价\\loan-pricing-892\\loan-pricing-892-v2.0"
]
}
}

View File

@@ -1,24 +0,0 @@
{
"paths": {
"specs": ".claude/specs",
"steering": ".claude/steering",
"settings": ".claude/settings"
},
"views": {
"specs": {
"visible": true
},
"steering": {
"visible": true
},
"mcp": {
"visible": true
},
"hooks": {
"visible": true
},
"settings": {
"visible": false
}
}
}

91
.gitignore vendored
View File

@@ -1,53 +1,48 @@
###################################################################### ######################################################################
# Build Tools # Build Tools
.gradle .gradle
/build/ /build/
!gradle/wrapper/gradle-wrapper.jar !gradle/wrapper/gradle-wrapper.jar
target/ target/
!.mvn/wrapper/maven-wrapper.jar !.mvn/wrapper/maven-wrapper.jar
###################################################################### ######################################################################
# IDE # IDE
### STS ### ### STS ###
.apt_generated .apt_generated
.classpath .classpath
.factorypath .factorypath
.project .project
.settings .settings
.springBeans .springBeans
### IntelliJ IDEA ### ### IntelliJ IDEA ###
.idea .idea
*.iws *.iws
*.iml *.iml
*.ipr *.ipr
### JRebel ### ### JRebel ###
rebel.xml rebel.xml
### NetBeans ### ### NetBeans ###
nbproject/private/ nbproject/private/
build/* build/*
nbbuild/ nbbuild/
dist/ dist/
nbdist/ nbdist/
.nb-gradle/ .nb-gradle/
###################################################################### ######################################################################
# Others # Others
.DS_Store
*.log *.log
*.xml.versionsBackup *.xml.versionsBackup
*.swp *.swp
!*/build/*.java !*/build/*.java
!*/build/*.html !*/build/*.html
!*/build/*.xml !*/build/*.xml
logs/
ruoyi-ui/dist.zip
.playwright-cli

View File

@@ -1,6 +0,0 @@
- generic [ref=e2]:
- heading "Example Domain" [level=1] [ref=e3]
- paragraph [ref=e4]: This domain is for use in documentation examples without needing permission. Avoid use in operations.
- paragraph [ref=e5]:
- link "Learn more" [ref=e6] [cursor=pointer]:
- /url: https://iana.org/domains/example

View File

@@ -1,6 +0,0 @@
- generic [ref=e2]:
- heading "Example Domain" [level=1] [ref=e3]
- paragraph [ref=e4]: This domain is for use in documentation examples without needing permission. Avoid use in operations.
- paragraph [ref=e5]:
- link "Learn more" [ref=e6] [cursor=pointer]:
- /url: https://iana.org/domains/example

View File

@@ -1,22 +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]: "123456"
- 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:
- alert [ref=e29]:
- generic [ref=e30]:
- paragraph [ref=e31]: 用户不存在/密码错误

View File

@@ -0,0 +1,20 @@
- 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:

View File

@@ -0,0 +1 @@
- generic [ref=e2]:

View File

@@ -0,0 +1,191 @@
- 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:

View File

@@ -0,0 +1 @@
- generic [ref=e2]:

View File

@@ -0,0 +1 @@
- generic [ref=e2]:

View File

@@ -0,0 +1 @@
- generic [ref=e2]:

View File

@@ -0,0 +1,28 @@
- 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异常

View File

@@ -1,12 +1,12 @@
- generic [ref=e2]: - generic [ref=e2]:
- generic [ref=e3]: - generic [ref=e3]:
- generic [ref=e4]: - generic [ref=e4]:
- heading "上虞利率定价系统" [level=3] [ref=e5] - heading "若依管理系统" [level=3] [ref=e5]
- generic [ref=e8]: - generic [ref=e8]:
- textbox "账号" [ref=e9] - textbox "账号" [ref=e9]: admin
- img [ref=e11] - img [ref=e11]
- generic [ref=e15]: - generic [ref=e15]:
- textbox "密码" [ref=e16] - textbox "密码" [ref=e16]: admin123
- img [ref=e18] - img [ref=e18]
- generic [ref=e20] [cursor=pointer]: - generic [ref=e20] [cursor=pointer]:
- generic [ref=e21]: - generic [ref=e21]:

View File

@@ -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.1</h1> <h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">RuoYi v3.9.2</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.1-brightgreen.svg"></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/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,16 +13,37 @@
若依是一套全部开源的快速开发平台,毫无保留给个人及企业免费使用。 若依是一套全部开源的快速开发平台,毫无保留给个人及企业免费使用。
* 本仓库为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)&nbsp;&nbsp; * 阿里云折扣场:[点我进入](http://aly.ruoyi.vip),腾讯云秒杀场:[点我进入](http://txy.ruoyi.vip)&nbsp;&nbsp;
# 版本分支
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. 用户管理:用户是系统操作者,该功能主要完成系统用户配置。
@@ -92,4 +113,4 @@
## 若依前后端分离交流群 ## 若依前后端分离交流群
QQ群 [![加入QQ群](https://img.shields.io/badge/已满-937441-blue.svg)](https://jq.qq.com/?_wv=1027&k=5bVB1og) [![加入QQ群](https://img.shields.io/badge/已满-887144332-blue.svg)](https://jq.qq.com/?_wv=1027&k=5eiA4DH) [![加入QQ群](https://img.shields.io/badge/已满-180251782-blue.svg)](https://jq.qq.com/?_wv=1027&k=5AxMKlC) [![加入QQ群](https://img.shields.io/badge/已满-104180207-blue.svg)](https://jq.qq.com/?_wv=1027&k=51G72yr) [![加入QQ群](https://img.shields.io/badge/已满-186866453-blue.svg)](https://jq.qq.com/?_wv=1027&k=VvjN2nvu) [![加入QQ群](https://img.shields.io/badge/已满-201396349-blue.svg)](https://jq.qq.com/?_wv=1027&k=5vYAqA05) [![加入QQ群](https://img.shields.io/badge/已满-101456076-blue.svg)](https://jq.qq.com/?_wv=1027&k=kOIINEb5) [![加入QQ群](https://img.shields.io/badge/已满-101539465-blue.svg)](https://jq.qq.com/?_wv=1027&k=UKtX5jhs) [![加入QQ群](https://img.shields.io/badge/已满-264312783-blue.svg)](https://jq.qq.com/?_wv=1027&k=EI9an8lJ) [![加入QQ群](https://img.shields.io/badge/已满-167385320-blue.svg)](https://jq.qq.com/?_wv=1027&k=SWCtLnMz) [![加入QQ群](https://img.shields.io/badge/已满-104748341-blue.svg)](https://jq.qq.com/?_wv=1027&k=96Dkdq0k) [![加入QQ群](https://img.shields.io/badge/已满-160110482-blue.svg)](https://jq.qq.com/?_wv=1027&k=0fsNiYZt) [![加入QQ群](https://img.shields.io/badge/已满-170801498-blue.svg)](https://jq.qq.com/?_wv=1027&k=7xw4xUG1) [![加入QQ群](https://img.shields.io/badge/已满-108482800-blue.svg)](https://jq.qq.com/?_wv=1027&k=eCx8eyoJ) [![加入QQ群](https://img.shields.io/badge/已满-101046199-blue.svg)](https://jq.qq.com/?_wv=1027&k=SpyH2875) [![加入QQ群](https://img.shields.io/badge/已满-136919097-blue.svg)](https://jq.qq.com/?_wv=1027&k=tKEt51dz) [![加入QQ群](https://img.shields.io/badge/已满-143961921-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=0vBbSb0ztbBgVtn3kJS-Q4HUNYwip89G&authKey=8irq5PhutrZmWIvsUsklBxhj57l%2F1nOZqjzigkXZVoZE451GG4JHPOqW7AW6cf0T&noverify=0&group_code=143961921) [![加入QQ群](https://img.shields.io/badge/已满-174951577-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=ZFAPAbp09S2ltvwrJzp7wGlbopsc0rwi&authKey=HB2cxpxP2yspk%2Bo3WKTBfktRCccVkU26cgi5B16u0KcAYrVu7sBaE7XSEqmMdFQp&noverify=0&group_code=174951577) [![加入QQ群](https://img.shields.io/badge/已满-161281055-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=Fn2aF5IHpwsy8j6VlalNJK6qbwFLFHat&authKey=uyIT%2B97x2AXj3odyXpsSpVaPMC%2Bidw0LxG5MAtEqlrcBcWJUA%2FeS43rsF1Tg7IRJ&noverify=0&group_code=161281055) [![加入QQ群](https://img.shields.io/badge/已满-138988063-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=XIzkm_mV2xTsUtFxo63bmicYoDBA6Ifm&authKey=dDW%2F4qsmw3x9govoZY9w%2FoWAoC4wbHqGal%2BbqLzoS6VBarU8EBptIgPKN%2FviyC8j&noverify=0&group_code=138988063) [![加入QQ群](https://img.shields.io/badge/已满-151450850-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=DkugnCg68PevlycJSKSwjhFqfIgrWWwR&authKey=pR1Pa5lPIeGF%2FFtIk6d%2FGB5qFi0EdvyErtpQXULzo03zbhopBHLWcuqdpwY241R%2F&noverify=0&group_code=151450850) [![加入QQ群](https://img.shields.io/badge/已满-224622315-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=F58bgRa-Dp-rsQJThiJqIYv8t4-lWfXh&authKey=UmUs4CVG5OPA1whvsa4uSespOvyd8%2FAr9olEGaWAfdLmfKQk%2FVBp2YU3u2xXXt76&noverify=0&group_code=224622315) [![加入QQ群](https://img.shields.io/badge/已满-287842588-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=Nxb2EQ5qozWa218Wbs7zgBnjLSNk_tVT&authKey=obBKXj6SBKgrFTJZx0AqQnIYbNOvBB2kmgwWvGhzxR67RoRr84%2Bus5OadzMcdJl5&noverify=0&group_code=287842588) [![加入QQ群](https://img.shields.io/badge/已满-187944233-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=numtK1M_I4eVd2Gvg8qtbuL8JgX42qNh&authKey=giV9XWMaFZTY%2FqPlmWbkB9g3fi0Ev5CwEtT9Tgei0oUlFFCQLDp4ozWRiVIzubIm&noverify=0&group_code=187944233) [![加入QQ群](https://img.shields.io/badge/已满-228578329-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=G6r5KGCaa3pqdbUSXNIgYloyb8e0_L0D&authKey=4w8tF1eGW7%2FedWn%2FHAypQksdrML%2BDHolQSx7094Agm7Luakj9EbfPnSTxSi2T1LQ&noverify=0&group_code=228578329) [![加入QQ群](https://img.shields.io/badge/已满-191164766-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=GsOo-OLz53J8y_9TPoO6XXSGNRTgbFxA&authKey=R7Uy%2Feq%2BZsoKNqHvRKhiXpypW7DAogoWapOawUGHokJSBIBIre2%2FoiAZeZBSLuBc&noverify=0&group_code=191164766) [![加入QQ群](https://img.shields.io/badge/174569686-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=PmYavuzsOthVqfdAPbo4uAeIbu7Ttjgc&authKey=p52l8%2FXa4PS1JcEmS3VccKSwOPJUZ1ZfQ69MEKzbrooNUljRtlKjvsXf04bxNp3G&noverify=0&group_code=174569686) 点击按钮入群。 QQ群 [![加入QQ群](https://img.shields.io/badge/已满-937441-blue.svg)](https://jq.qq.com/?_wv=1027&k=5bVB1og) [![加入QQ群](https://img.shields.io/badge/已满-887144332-blue.svg)](https://jq.qq.com/?_wv=1027&k=5eiA4DH) [![加入QQ群](https://img.shields.io/badge/已满-180251782-blue.svg)](https://jq.qq.com/?_wv=1027&k=5AxMKlC) [![加入QQ群](https://img.shields.io/badge/已满-104180207-blue.svg)](https://jq.qq.com/?_wv=1027&k=51G72yr) [![加入QQ群](https://img.shields.io/badge/已满-186866453-blue.svg)](https://jq.qq.com/?_wv=1027&k=VvjN2nvu) [![加入QQ群](https://img.shields.io/badge/已满-201396349-blue.svg)](https://jq.qq.com/?_wv=1027&k=5vYAqA05) [![加入QQ群](https://img.shields.io/badge/已满-101456076-blue.svg)](https://jq.qq.com/?_wv=1027&k=kOIINEb5) [![加入QQ群](https://img.shields.io/badge/已满-101539465-blue.svg)](https://jq.qq.com/?_wv=1027&k=UKtX5jhs) [![加入QQ群](https://img.shields.io/badge/已满-264312783-blue.svg)](https://jq.qq.com/?_wv=1027&k=EI9an8lJ) [![加入QQ群](https://img.shields.io/badge/已满-167385320-blue.svg)](https://jq.qq.com/?_wv=1027&k=SWCtLnMz) [![加入QQ群](https://img.shields.io/badge/已满-104748341-blue.svg)](https://jq.qq.com/?_wv=1027&k=96Dkdq0k) [![加入QQ群](https://img.shields.io/badge/已满-160110482-blue.svg)](https://jq.qq.com/?_wv=1027&k=0fsNiYZt) [![加入QQ群](https://img.shields.io/badge/已满-170801498-blue.svg)](https://jq.qq.com/?_wv=1027&k=7xw4xUG1) [![加入QQ群](https://img.shields.io/badge/已满-108482800-blue.svg)](https://jq.qq.com/?_wv=1027&k=eCx8eyoJ) [![加入QQ群](https://img.shields.io/badge/已满-101046199-blue.svg)](https://jq.qq.com/?_wv=1027&k=SpyH2875) [![加入QQ群](https://img.shields.io/badge/已满-136919097-blue.svg)](https://jq.qq.com/?_wv=1027&k=tKEt51dz) [![加入QQ群](https://img.shields.io/badge/已满-143961921-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=0vBbSb0ztbBgVtn3kJS-Q4HUNYwip89G&authKey=8irq5PhutrZmWIvsUsklBxhj57l%2F1nOZqjzigkXZVoZE451GG4JHPOqW7AW6cf0T&noverify=0&group_code=143961921) [![加入QQ群](https://img.shields.io/badge/已满-174951577-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=ZFAPAbp09S2ltvwrJzp7wGlbopsc0rwi&authKey=HB2cxpxP2yspk%2Bo3WKTBfktRCccVkU26cgi5B16u0KcAYrVu7sBaE7XSEqmMdFQp&noverify=0&group_code=174951577) [![加入QQ群](https://img.shields.io/badge/已满-161281055-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=Fn2aF5IHpwsy8j6VlalNJK6qbwFLFHat&authKey=uyIT%2B97x2AXj3odyXpsSpVaPMC%2Bidw0LxG5MAtEqlrcBcWJUA%2FeS43rsF1Tg7IRJ&noverify=0&group_code=161281055) [![加入QQ群](https://img.shields.io/badge/已满-138988063-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=XIzkm_mV2xTsUtFxo63bmicYoDBA6Ifm&authKey=dDW%2F4qsmw3x9govoZY9w%2FoWAoC4wbHqGal%2BbqLzoS6VBarU8EBptIgPKN%2FviyC8j&noverify=0&group_code=138988063) [![加入QQ群](https://img.shields.io/badge/已满-151450850-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=DkugnCg68PevlycJSKSwjhFqfIgrWWwR&authKey=pR1Pa5lPIeGF%2FFtIk6d%2FGB5qFi0EdvyErtpQXULzo03zbhopBHLWcuqdpwY241R%2F&noverify=0&group_code=151450850) [![加入QQ群](https://img.shields.io/badge/已满-224622315-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=F58bgRa-Dp-rsQJThiJqIYv8t4-lWfXh&authKey=UmUs4CVG5OPA1whvsa4uSespOvyd8%2FAr9olEGaWAfdLmfKQk%2FVBp2YU3u2xXXt76&noverify=0&group_code=224622315) [![加入QQ群](https://img.shields.io/badge/已满-287842588-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=Nxb2EQ5qozWa218Wbs7zgBnjLSNk_tVT&authKey=obBKXj6SBKgrFTJZx0AqQnIYbNOvBB2kmgwWvGhzxR67RoRr84%2Bus5OadzMcdJl5&noverify=0&group_code=287842588) [![加入QQ群](https://img.shields.io/badge/已满-187944233-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=numtK1M_I4eVd2Gvg8qtbuL8JgX42qNh&authKey=giV9XWMaFZTY%2FqPlmWbkB9g3fi0Ev5CwEtT9Tgei0oUlFFCQLDp4ozWRiVIzubIm&noverify=0&group_code=187944233) [![加入QQ群](https://img.shields.io/badge/已满-228578329-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=G6r5KGCaa3pqdbUSXNIgYloyb8e0_L0D&authKey=4w8tF1eGW7%2FedWn%2FHAypQksdrML%2BDHolQSx7094Agm7Luakj9EbfPnSTxSi2T1LQ&noverify=0&group_code=228578329) [![加入QQ群](https://img.shields.io/badge/已满-191164766-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=GsOo-OLz53J8y_9TPoO6XXSGNRTgbFxA&authKey=R7Uy%2Feq%2BZsoKNqHvRKhiXpypW7DAogoWapOawUGHokJSBIBIre2%2FoiAZeZBSLuBc&noverify=0&group_code=191164766) [![加入QQ群](https://img.shields.io/badge/已满-174569686-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=PmYavuzsOthVqfdAPbo4uAeIbu7Ttjgc&authKey=p52l8%2FXa4PS1JcEmS3VccKSwOPJUZ1ZfQ69MEKzbrooNUljRtlKjvsXf04bxNp3G&noverify=0&group_code=174569686) [![加入QQ群](https://img.shields.io/badge/127358632-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=M9y5NjAl44lAL_Vh2crmEehZU_PMU6KS&authKey=ZSDz8hEREWSaPuxQV3gEwqGIaGjfRNnkB4rJjf0IvXhrSUGSGwQFmBA%2Boe8HFxyl&noverify=0&group_code=127358632) 点击按钮入群。

BIN
bin/.DS_Store vendored

Binary file not shown.

View File

@@ -1,12 +1,12 @@
@echo off @echo off
echo. echo.
echo [信息] 清理工程target生成路径。 echo [信息] 清理工程target生成路径。
echo. echo.
%~d0 %~d0
cd %~dp0 cd %~dp0
cd .. cd ..
call mvn clean call mvn clean
pause pause

View File

@@ -1,12 +1,12 @@
@echo off @echo off
echo. echo.
echo [信息] 打包Web工程生成war/jar包文件。 echo [信息] 打包Web工程生成war/jar包文件。
echo. echo.
%~d0 %~d0
cd %~dp0 cd %~dp0
cd .. cd ..
call mvn clean package -Dmaven.test.skip=true call mvn clean package -Dmaven.test.skip=true
pause pause

0
bin/prod/restart_java_test.sh Normal file → Executable file
View File

0
bin/restart_java_backend_test.sh Normal file → Executable file
View File

View File

@@ -1,14 +1,14 @@
@echo off @echo off
echo. echo.
echo [信息] 使用Jar命令运行Web工程。 echo [信息] 使用Jar命令运行Web工程。
echo. echo.
cd %~dp0 cd %~dp0
cd ../ruoyi-admin/target cd ../ruoyi-admin/target
set JAVA_OPTS=-Xms256m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m set JAVA_OPTS=-Xms256m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m
java -jar %JAVA_OPTS% ruoyi-admin.jar java -jar %JAVA_OPTS% ruoyi-admin.jar
cd bin cd bin
pause pause

View File

@@ -0,0 +1,43 @@
# 本地 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`

View File

@@ -0,0 +1,147 @@
# 本地 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`
在不新增模块、不扩散复杂度的前提下,满足开发与部署两端的实际需要。

View File

@@ -0,0 +1,39 @@
# 东方通替换 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`

View File

@@ -0,0 +1,41 @@
# 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 可运行实现

View File

@@ -0,0 +1,37 @@
# 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` 控制
- 测试完成后要关闭前端调试进程

View File

@@ -0,0 +1,120 @@
# 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. 产出物
本次任务最终需产出:
- 本设计文档
- 后端实施计划文档
- 前端实施计划文档
- 迁移实施记录文档

View File

@@ -0,0 +1,19 @@
# 个人流程最终测算利率展示实施记录
## 修改时间
- 2026-04-11
## 修改内容
- 调整流程列表后端查询:个人客户列表“测算利率”改为读取 `model_retail_output_fields.final_calculate_rate`
- 调整个人流程详情左侧展示:标签改为“最终测算利率”,显示字段改为 `retailOutput.finalCalculateRate`
- 调整个人流程详情后端组装:`loanPricingWorkflow.loanRate` 改为取个人模型输出的 `finalCalculateRate`
## 影响范围
- 个人流程列表
- 个人流程详情左侧关键信息
- 企业流程列表与详情保持现状,不做改动
## 验证计划
- 后端单元测试验证个人详情取 `finalCalculateRate`
- 后端静态测试验证列表 SQL 的个人分支查询 `mr.final_calculate_rate`
- 前端静态测试验证个人详情展示 `finalCalculateRate`

View File

@@ -0,0 +1,17 @@
# 流程详情卡片顺序调整实施记录
## 修改时间
- 2026-04-11
## 修改内容
- 调整个人流程详情页右侧卡片顺序,将模型输出卡片移动到流程详情卡片上方
- 调整企业流程详情页右侧卡片顺序,将模型输出卡片移动到流程详情卡片上方
- 新增前端静态校验,约束个人与企业详情组件的卡片顺序
## 影响范围
- 个人流程详情页面布局
- 企业流程详情页面布局
## 验证计划
- 执行前端静态测试,确认卡片顺序断言通过
- 启动前端页面并在浏览器中检查个人、企业详情页卡片顺序

View File

@@ -0,0 +1,34 @@
# 本地 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 部署产物

View File

@@ -0,0 +1,25 @@
# 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` 转发到后端容器

View File

@@ -0,0 +1,105 @@
# 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` 运行态查询仍需继续收口

513
pom.xml
View File

@@ -1,191 +1,218 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" <project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi</artifactId> <artifactId>ruoyi</artifactId>
<version>3.9.1</version> <version>3.9.2</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.1</ruoyi.version> <ruoyi.version>3.9.2</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>17</java.version> <java.version>1.8</java.version>
<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version> <maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
<mybatis-spring-boot.version>3.0.5</mybatis-spring-boot.version> <spring-boot.version>2.5.15</spring-boot.version>
<druid.version>1.2.27</druid.version> <druid.version>1.2.28</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>2.1.1</pagehelper.boot.version> <pagehelper.boot.version>1.4.7</pagehelper.boot.version>
<fastjson.version>2.0.60</fastjson.version> <fastjson.version>2.0.61</fastjson.version>
<oshi.version>6.9.1</oshi.version> <oshi.version>6.10.0</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>
<quartz.version>2.5.2</quartz.version> <mybatis-plus.version>3.5.7</mybatis-plus.version>
<mysql.version>8.2.0</mysql.version> <jsqlparser.version>4.5</jsqlparser.version>
<jaxb-api.version>2.3.1</jaxb-api.version> <!-- override dependency version -->
<jakarta.version>6.0.0</jakarta.version> <tomcat.version>9.0.112</tomcat.version>
<springdoc.version>2.8.14</springdoc.version> <logback.version>1.2.13</logback.version>
</properties> <spring-security.version>5.7.14</spring-security.version>
<spring-framework.version>5.3.39</spring-framework.version>
<!-- 依赖声明 --> </properties>
<dependencyManagement>
<dependencies> <!-- 依赖声明 -->
<dependencyManagement>
<!-- SpringBoot的依赖配置--> <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId> <!-- 覆盖SpringFramework的依赖配置-->
<artifactId>spring-boot-dependencies</artifactId> <dependency>
<version>3.5.8</version> <groupId>org.springframework</groupId>
<type>pom</type> <artifactId>spring-framework-bom</artifactId>
<scope>import</scope> <version>${spring-framework.version}</version>
</dependency> <type>pom</type>
<scope>import</scope>
<!-- 阿里数据库连接池 --> </dependency>
<dependency>
<groupId>com.alibaba</groupId> <!-- 覆盖SpringSecurity的依赖配置-->
<artifactId>druid-spring-boot-3-starter</artifactId> <dependency>
<version>${druid.version}</version> <groupId>org.springframework.security</groupId>
</dependency> <artifactId>spring-security-bom</artifactId>
<version>${spring-security.version}</version>
<!-- 解析客户端操作系统、浏览器等 --> <type>pom</type>
<dependency> <scope>import</scope>
<groupId>nl.basjes.parse.useragent</groupId> </dependency>
<artifactId>yauaa</artifactId>
<version>${yauaa.version}</version> <!-- SpringBoot的依赖配置-->
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<!-- pagehelper 分页插件 --> <artifactId>spring-boot-dependencies</artifactId>
<dependency> <version>${spring-boot.version}</version>
<groupId>com.github.pagehelper</groupId> <type>pom</type>
<artifactId>pagehelper-spring-boot-starter</artifactId> <scope>import</scope>
<version>${pagehelper.boot.version}</version> </dependency>
</dependency>
<!-- 覆盖logback的依赖配置-->
<dependency> <dependency>
<groupId>org.mybatis.spring.boot</groupId> <groupId>ch.qos.logback</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId> <artifactId>logback-core</artifactId>
<version>${mybatis-spring-boot.version}</version> <version>${logback.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.mysql</groupId> <groupId>ch.qos.logback</groupId>
<artifactId>mysql-connector-j</artifactId> <artifactId>logback-classic</artifactId>
<version>${mysql.version}</version> <version>${logback.version}</version>
</dependency> </dependency>
<dependency> <!-- 覆盖tomcat的依赖配置-->
<groupId>javax.xml.bind</groupId> <dependency>
<artifactId>jaxb-api</artifactId> <groupId>org.apache.tomcat.embed</groupId>
<version>${jaxb-api.version}</version> <artifactId>tomcat-embed-core</artifactId>
</dependency> <version>${tomcat.version}</version>
</dependency>
<dependency>
<groupId>jakarta.servlet</groupId> <dependency>
<artifactId>jakarta.servlet-api</artifactId> <groupId>org.apache.tomcat.embed</groupId>
<version>${jakarta.version}</version> <artifactId>tomcat-embed-el</artifactId>
</dependency> <version>${tomcat.version}</version>
</dependency>
<!-- 获取系统信息 -->
<dependency> <dependency>
<groupId>com.github.oshi</groupId> <groupId>org.apache.tomcat.embed</groupId>
<artifactId>oshi-core</artifactId> <artifactId>tomcat-embed-websocket</artifactId>
<version>${oshi.version}</version> <version>${tomcat.version}</version>
</dependency> </dependency>
<!-- spring-doc --> <!-- 阿里数据库连接池 -->
<dependency> <dependency>
<groupId>org.springdoc</groupId> <groupId>com.alibaba</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId> <artifactId>druid-spring-boot-starter</artifactId>
<version>${springdoc.version}</version> <version>${druid.version}</version>
</dependency> </dependency>
<!-- io常用工具类 --> <!-- 解析客户端操作系统、浏览器等 -->
<dependency> <dependency>
<groupId>commons-io</groupId> <groupId>nl.basjes.parse.useragent</groupId>
<artifactId>commons-io</artifactId> <artifactId>yauaa</artifactId>
<version>${commons.io.version}</version> <version>${yauaa.version}</version>
</dependency> </dependency>
<!-- excel工具 --> <!-- pagehelper 分页插件 -->
<dependency> <dependency>
<groupId>org.apache.poi</groupId> <groupId>com.github.pagehelper</groupId>
<artifactId>poi-ooxml</artifactId> <artifactId>pagehelper-spring-boot-starter</artifactId>
<version>${poi.version}</version> <version>${pagehelper.boot.version}</version>
</dependency> </dependency>
<!-- velocity代码生成使用模板 --> <!-- 获取系统信息 -->
<dependency> <dependency>
<groupId>org.apache.velocity</groupId> <groupId>com.github.oshi</groupId>
<artifactId>velocity-engine-core</artifactId> <artifactId>oshi-core</artifactId>
<version>${velocity.version}</version> <version>${oshi.version}</version>
</dependency> </dependency>
<!-- 定时任务 --> <!-- Swagger3依赖 -->
<dependency> <dependency>
<groupId>org.quartz-scheduler</groupId> <groupId>io.springfox</groupId>
<artifactId>quartz</artifactId> <artifactId>springfox-boot-starter</artifactId>
<version>${quartz.version}</version> <version>${swagger.version}</version>
</dependency> <exclusions>
<exclusion>
<!-- 阿里JSON解析器 --> <groupId>io.swagger</groupId>
<dependency> <artifactId>swagger-models</artifactId>
<groupId>com.alibaba.fastjson2</groupId> </exclusion>
<artifactId>fastjson2</artifactId> </exclusions>
<version>${fastjson.version}</version> </dependency>
</dependency>
<!-- io常用工具类 -->
<!-- Token生成与解析--> <dependency>
<dependency> <groupId>commons-io</groupId>
<groupId>io.jsonwebtoken</groupId> <artifactId>commons-io</artifactId>
<artifactId>jjwt</artifactId> <version>${commons.io.version}</version>
<version>${jwt.version}</version> </dependency>
</dependency>
<!-- excel工具 -->
<!-- 验证码 --> <dependency>
<dependency> <groupId>org.apache.poi</groupId>
<groupId>pro.fessional</groupId> <artifactId>poi-ooxml</artifactId>
<artifactId>kaptcha</artifactId> <version>${poi.version}</version>
<version>${kaptcha.version}</version> </dependency>
</dependency>
<!-- velocity代码生成使用模板 -->
<!-- 定时任务--> <dependency>
<dependency> <groupId>org.apache.velocity</groupId>
<groupId>com.ruoyi</groupId> <artifactId>velocity-engine-core</artifactId>
<artifactId>ruoyi-quartz</artifactId> <version>${velocity.version}</version>
<version>${ruoyi.version}</version> </dependency>
</dependency>
<!-- 阿里JSON解析器 -->
<!-- 代码生成--> <dependency>
<dependency> <groupId>com.alibaba.fastjson2</groupId>
<groupId>com.ruoyi</groupId> <artifactId>fastjson2</artifactId>
<artifactId>ruoyi-generator</artifactId> <version>${fastjson.version}</version>
<version>${ruoyi.version}</version> </dependency>
</dependency>
<!-- Token生成与解析-->
<!-- 核心模块--> <dependency>
<dependency> <groupId>io.jsonwebtoken</groupId>
<groupId>com.ruoyi</groupId> <artifactId>jjwt</artifactId>
<artifactId>ruoyi-framework</artifactId> <version>${jwt.version}</version>
<version>${ruoyi.version}</version> </dependency>
</dependency>
<!-- 验证码 -->
<!-- 系统模块--> <dependency>
<dependency> <groupId>pro.fessional</groupId>
<groupId>com.ruoyi</groupId> <artifactId>kaptcha</artifactId>
<artifactId>ruoyi-system</artifactId> <version>${kaptcha.version}</version>
<version>${ruoyi.version}</version> </dependency>
</dependency>
<!-- 定时任务-->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-quartz</artifactId>
<version>${ruoyi.version}</version>
</dependency>
<!-- 代码生成-->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-generator</artifactId>
<version>${ruoyi.version}</version>
</dependency>
<!-- 核心模块-->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-framework</artifactId>
<version>${ruoyi.version}</version>
</dependency>
<!-- 系统模块-->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-system</artifactId>
<version>${ruoyi.version}</version>
</dependency>
<!-- 通用工具--> <!-- 通用工具-->
<dependency> <dependency>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
@@ -200,64 +227,70 @@
<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>
<modules> <modules>
<module>ruoyi-admin</module> <module>ruoyi-admin</module>
<module>ruoyi-framework</module> <module>ruoyi-framework</module>
<module>ruoyi-system</module> <module>ruoyi-system</module>
<module>ruoyi-quartz</module> <module>ruoyi-quartz</module>
<module>ruoyi-generator</module> <module>ruoyi-generator</module>
<module>ruoyi-common</module> <module>ruoyi-common</module>
<module>ruoyi-loan-pricing</module> <module>ruoyi-loan-pricing</module>
</modules> </modules>
<packaging>pom</packaging> <packaging>pom</packaging>
<build> <build>
<plugins> <plugins>
<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.13.0</version> <version>3.1</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> </plugins>
<plugin> </build>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId> <repositories>
<version>3.3.0</version> <repository>
</plugin> <id>public</id>
</plugins> <name>aliyun nexus</name>
</build> <url>https://maven.aliyun.com/repository/public</url>
<releases>
<repositories> <enabled>true</enabled>
<repository> </releases>
<id>public</id> </repository>
<name>aliyun nexus</name> </repositories>
<url>https://maven.aliyun.com/repository/public</url>
<releases> <pluginRepositories>
<enabled>true</enabled> <pluginRepository>
</releases> <id>public</id>
</repository> <name>aliyun nexus</name>
</repositories> <url>https://maven.aliyun.com/repository/public</url>
<releases>
<pluginRepositories> <enabled>true</enabled>
<pluginRepository> </releases>
<id>public</id> <snapshots>
<name>aliyun nexus</name> <enabled>false</enabled>
<url>https://maven.aliyun.com/repository/public</url> </snapshots>
<releases> </pluginRepository>
<enabled>true</enabled> </pluginRepositories>
</releases>
<snapshots> </project>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</project>

BIN
ruoyi-admin/.DS_Store vendored

Binary file not shown.

View File

@@ -1,53 +1,60 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" <project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent> <parent>
<artifactId>ruoyi</artifactId> <artifactId>ruoyi</artifactId>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<version>3.9.1</version> <version>3.9.2</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging> <packaging>jar</packaging>
<artifactId>ruoyi-admin</artifactId> <artifactId>ruoyi-admin</artifactId>
<description> <description>
web服务入口 web服务入口
</description> </description>
<dependencies> <dependencies>
<!-- spring-boot-devtools --> <!-- spring-boot-devtools -->
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId> <artifactId>spring-boot-devtools</artifactId>
<optional>true</optional> <!-- 表示依赖不会传递 --> <optional>true</optional> <!-- 表示依赖不会传递 -->
</dependency> </dependency>
<!-- spring-doc --> <!-- swagger3-->
<dependency> <dependency>
<groupId>org.springdoc</groupId> <groupId>io.springfox</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId> <artifactId>springfox-boot-starter</artifactId>
</dependency> </dependency>
<!-- Mysql驱动包 --> <!-- 防止进入swagger页面报类型转换错误排除3.0.0中的引用手动增加1.6.2版本 -->
<dependency> <dependency>
<groupId>com.mysql</groupId> <groupId>io.swagger</groupId>
<artifactId>mysql-connector-j</artifactId> <artifactId>swagger-models</artifactId>
</dependency> <version>1.6.2</version>
</dependency>
<!-- 核心模块-->
<dependency> <!-- Mysql驱动包 -->
<groupId>com.ruoyi</groupId> <dependency>
<artifactId>ruoyi-framework</artifactId> <groupId>mysql</groupId>
</dependency> <artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- 定时任务-->
<dependency> <!-- 核心模块-->
<groupId>com.ruoyi</groupId> <dependency>
<artifactId>ruoyi-quartz</artifactId> <groupId>com.ruoyi</groupId>
</dependency> <artifactId>ruoyi-framework</artifactId>
</dependency>
<!-- 定时任务-->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-quartz</artifactId>
</dependency>
<!-- 代码生成--> <!-- 代码生成-->
<dependency> <dependency>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
@@ -60,42 +67,36 @@
<artifactId>ruoyi-loan-pricing</artifactId> <artifactId>ruoyi-loan-pricing</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
<build> <build>
<plugins> <plugins>
<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>3.5.4</version> <version>2.5.15</version>
<configuration> <configuration>
<addResources>true</addResources> <fork>true</fork> <!-- 如果没有该配置devtools不会生效 -->
</configuration> </configuration>
<executions> <executions>
<execution> <execution>
<goals> <goals>
<goal>repackage</goal> <goal>repackage</goal>
</goals> </goals>
</execution> </execution>
</executions> </executions>
</plugin> </plugin>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId> <artifactId>maven-war-plugin</artifactId>
<version>3.1.0</version> <version>3.1.0</version>
<configuration> <configuration>
<failOnMissingWebXml>false</failOnMissingWebXml> <failOnMissingWebXml>false</failOnMissingWebXml>
<warName>${project.artifactId}</warName> <warName>${project.artifactId}</warName>
</configuration> </configuration>
</plugin> </plugin>
</plugins> </plugins>
<finalName>${project.artifactId}</finalName> <finalName>${project.artifactId}</finalName>
</build> </build>
</project> </project>

View File

@@ -1,30 +1,30 @@
package com.ruoyi; package com.ruoyi;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
/** /**
* 启动程序 * 启动程序
* *
* @author ruoyi * @author ruoyi
*/ */
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class }) @SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
public class RuoYiApplication public class RuoYiApplication
{ {
public static void main(String[] args) public static void main(String[] args)
{ {
// System.setProperty("spring.devtools.restart.enabled", "false"); // System.setProperty("spring.devtools.restart.enabled", "false");
SpringApplication.run(RuoYiApplication.class, args); SpringApplication.run(RuoYiApplication.class, args);
System.out.println("(♥◠‿◠)ノ゙ 若依启动成功 ლ(´ڡ`ლ)゙ \n" + System.out.println("(♥◠‿◠)ノ゙ 若依启动成功 ლ(´ڡ`ლ)゙ \n" +
" .-------. ____ __ \n" + " .-------. ____ __ \n" +
" | _ _ \\ \\ \\ / / \n" + " | _ _ \\ \\ \\ / / \n" +
" | ( ' ) | \\ _. / ' \n" + " | ( ' ) | \\ _. / ' \n" +
" |(_ o _) / _( )_ .' \n" + " |(_ o _) / _( )_ .' \n" +
" | (_,_).' __ ___(_ o _)' \n" + " | (_,_).' __ ___(_ o _)' \n" +
" | |\\ \\ | || |(_,_)' \n" + " | |\\ \\ | || |(_,_)' \n" +
" | | \\ `' /| `-' / \n" + " | | \\ `' /| `-' / \n" +
" | | \\ / \\ / \n" + " | | \\ / \\ / \n" +
" ''-' `'-' `-..-' "); " ''-' `'-' `-..-' ");
} }
} }

View File

@@ -1,18 +1,18 @@
package com.ruoyi; package com.ruoyi;
import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
/** /**
* web容器中进行部署 * web容器中进行部署
* *
* @author ruoyi * @author ruoyi
*/ */
public class RuoYiServletInitializer extends SpringBootServletInitializer public class RuoYiServletInitializer extends SpringBootServletInitializer
{ {
@Override @Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) protected SpringApplicationBuilder configure(SpringApplicationBuilder application)
{ {
return application.sources(RuoYiApplication.class); return application.sources(RuoYiApplication.class);
} }
} }

View File

@@ -1,94 +1,94 @@
package com.ruoyi.web.controller.common; 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 jakarta.annotation.Resource; import javax.annotation.Resource;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
import jakarta.servlet.http.HttpServletResponse; import javax.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;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import com.google.code.kaptcha.Producer; import com.google.code.kaptcha.Producer;
import com.ruoyi.common.config.RuoYiConfig; import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.constant.CacheConstants; import com.ruoyi.common.constant.CacheConstants;
import com.ruoyi.common.constant.Constants; import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.AjaxResult; 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.sign.Base64; import com.ruoyi.common.utils.sign.Base64;
import com.ruoyi.common.utils.uuid.IdUtils; import com.ruoyi.common.utils.uuid.IdUtils;
import com.ruoyi.system.service.ISysConfigService; import com.ruoyi.system.service.ISysConfigService;
/** /**
* 验证码操作处理 * 验证码操作处理
* *
* @author ruoyi * @author ruoyi
*/ */
@RestController @RestController
public class CaptchaController public class CaptchaController
{ {
@Resource(name = "captchaProducer") @Resource(name = "captchaProducer")
private Producer captchaProducer; private Producer captchaProducer;
@Resource(name = "captchaProducerMath") @Resource(name = "captchaProducerMath")
private Producer captchaProducerMath; private Producer captchaProducerMath;
@Autowired @Autowired
private RedisCache redisCache; private RedisCache redisCache;
@Autowired @Autowired
private ISysConfigService configService; private ISysConfigService configService;
/** /**
* 生成验证码 * 生成验证码
*/ */
@GetMapping("/captchaImage") @GetMapping("/captchaImage")
public AjaxResult getCode(HttpServletResponse response) throws IOException public AjaxResult getCode(HttpServletResponse response) throws IOException
{ {
AjaxResult ajax = AjaxResult.success(); AjaxResult ajax = AjaxResult.success();
boolean captchaEnabled = configService.selectCaptchaEnabled(); boolean captchaEnabled = configService.selectCaptchaEnabled();
ajax.put("captchaEnabled", captchaEnabled); ajax.put("captchaEnabled", captchaEnabled);
if (!captchaEnabled) if (!captchaEnabled)
{ {
return ajax; return ajax;
} }
// 保存验证码信息 // 保存验证码信息
String uuid = IdUtils.simpleUUID(); String uuid = IdUtils.simpleUUID();
String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + uuid; String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + uuid;
String capStr = null, code = null; String capStr = null, code = null;
BufferedImage image = null; BufferedImage image = null;
// 生成验证码 // 生成验证码
String captchaType = RuoYiConfig.getCaptchaType(); String captchaType = RuoYiConfig.getCaptchaType();
if ("math".equals(captchaType)) if ("math".equals(captchaType))
{ {
String capText = captchaProducerMath.createText(); String capText = captchaProducerMath.createText();
capStr = capText.substring(0, capText.lastIndexOf("@")); capStr = capText.substring(0, capText.lastIndexOf("@"));
code = capText.substring(capText.lastIndexOf("@") + 1); code = capText.substring(capText.lastIndexOf("@") + 1);
image = captchaProducerMath.createImage(capStr); image = captchaProducerMath.createImage(capStr);
} }
else if ("char".equals(captchaType)) else if ("char".equals(captchaType))
{ {
capStr = code = captchaProducer.createText(); capStr = code = captchaProducer.createText();
image = captchaProducer.createImage(capStr); image = captchaProducer.createImage(capStr);
} }
redisCache.setCacheObject(verifyKey, code, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES); redisCache.setCacheObject(verifyKey, code, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES);
// 转换流信息写出 // 转换流信息写出
FastByteArrayOutputStream os = new FastByteArrayOutputStream(); FastByteArrayOutputStream os = new FastByteArrayOutputStream();
try try
{ {
ImageIO.write(image, "jpg", os); ImageIO.write(image, "jpg", os);
} }
catch (IOException e) catch (IOException e)
{ {
return AjaxResult.error(e.getMessage()); return AjaxResult.error(e.getMessage());
} }
ajax.put("uuid", uuid); ajax.put("uuid", uuid);
ajax.put("img", Base64.encode(os.toByteArray())); ajax.put("img", Base64.encode(os.toByteArray()));
return ajax; return ajax;
} }
} }

View File

@@ -1,162 +1,162 @@
package com.ruoyi.web.controller.common; package com.ruoyi.web.controller.common;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import jakarta.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse; import javax.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;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
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 org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
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.AjaxResult;
import com.ruoyi.common.utils.StringUtils; 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.framework.config.ServerConfig; import com.ruoyi.framework.config.ServerConfig;
/** /**
* 通用请求处理 * 通用请求处理
* *
* @author ruoyi * @author ruoyi
*/ */
@RestController @RestController
@RequestMapping("/common") @RequestMapping("/common")
public class CommonController public class CommonController
{ {
private static final Logger log = LoggerFactory.getLogger(CommonController.class); private static final Logger log = LoggerFactory.getLogger(CommonController.class);
@Autowired @Autowired
private ServerConfig serverConfig; private ServerConfig serverConfig;
private static final String FILE_DELIMITER = ","; private static final String FILE_DELIMITER = ",";
/** /**
* 通用下载请求 * 通用下载请求
* *
* @param fileName 文件名称 * @param fileName 文件名称
* @param delete 是否删除 * @param delete 是否删除
*/ */
@GetMapping("/download") @GetMapping("/download")
public void fileDownload(String fileName, Boolean delete, HttpServletResponse response, HttpServletRequest request) public void fileDownload(String fileName, Boolean delete, HttpServletResponse response, HttpServletRequest request)
{ {
try try
{ {
if (!FileUtils.checkAllowDownload(fileName)) if (!FileUtils.checkAllowDownload(fileName))
{ {
throw new Exception(StringUtils.format("文件名称({})非法,不允许下载。 ", fileName)); throw new Exception(StringUtils.format("文件名称({})非法,不允许下载。 ", fileName));
} }
String realFileName = System.currentTimeMillis() + fileName.substring(fileName.indexOf("_") + 1); String realFileName = System.currentTimeMillis() + fileName.substring(fileName.indexOf("_") + 1);
String filePath = RuoYiConfig.getDownloadPath() + fileName; String filePath = RuoYiConfig.getDownloadPath() + fileName;
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE); response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
FileUtils.setAttachmentResponseHeader(response, realFileName); FileUtils.setAttachmentResponseHeader(response, realFileName);
FileUtils.writeBytes(filePath, response.getOutputStream()); FileUtils.writeBytes(filePath, response.getOutputStream());
if (delete) if (delete)
{ {
FileUtils.deleteFile(filePath); FileUtils.deleteFile(filePath);
} }
} }
catch (Exception e) catch (Exception e)
{ {
log.error("下载文件失败", e); log.error("下载文件失败", e);
} }
} }
/** /**
* 通用上传请求(单个) * 通用上传请求(单个)
*/ */
@PostMapping("/upload") @PostMapping("/upload")
public AjaxResult uploadFile(MultipartFile file) throws Exception public AjaxResult uploadFile(MultipartFile file) throws Exception
{ {
try try
{ {
// 上传文件路径 // 上传文件路径
String filePath = RuoYiConfig.getUploadPath(); String filePath = RuoYiConfig.getUploadPath();
// 上传并返回新文件名称 // 上传并返回新文件名称
String fileName = FileUploadUtils.upload(filePath, file); String fileName = FileUploadUtils.upload(filePath, file);
String url = serverConfig.getUrl() + fileName; String url = serverConfig.getUrl() + fileName;
AjaxResult ajax = AjaxResult.success(); AjaxResult ajax = AjaxResult.success();
ajax.put("url", url); ajax.put("url", url);
ajax.put("fileName", fileName); ajax.put("fileName", fileName);
ajax.put("newFileName", FileUtils.getName(fileName)); ajax.put("newFileName", FileUtils.getName(fileName));
ajax.put("originalFilename", file.getOriginalFilename()); ajax.put("originalFilename", file.getOriginalFilename());
return ajax; return ajax;
} }
catch (Exception e) catch (Exception e)
{ {
return AjaxResult.error(e.getMessage()); return AjaxResult.error(e.getMessage());
} }
} }
/** /**
* 通用上传请求(多个) * 通用上传请求(多个)
*/ */
@PostMapping("/uploads") @PostMapping("/uploads")
public AjaxResult uploadFiles(List<MultipartFile> files) throws Exception public AjaxResult uploadFiles(List<MultipartFile> files) throws Exception
{ {
try try
{ {
// 上传文件路径 // 上传文件路径
String filePath = RuoYiConfig.getUploadPath(); String filePath = RuoYiConfig.getUploadPath();
List<String> urls = new ArrayList<String>(); List<String> urls = new ArrayList<String>();
List<String> fileNames = new ArrayList<String>(); List<String> fileNames = new ArrayList<String>();
List<String> newFileNames = new ArrayList<String>(); List<String> newFileNames = new ArrayList<String>();
List<String> originalFilenames = new ArrayList<String>(); List<String> originalFilenames = new ArrayList<String>();
for (MultipartFile file : files) for (MultipartFile file : files)
{ {
// 上传并返回新文件名称 // 上传并返回新文件名称
String fileName = FileUploadUtils.upload(filePath, file); String fileName = FileUploadUtils.upload(filePath, file);
String url = serverConfig.getUrl() + fileName; String url = serverConfig.getUrl() + fileName;
urls.add(url); urls.add(url);
fileNames.add(fileName); fileNames.add(fileName);
newFileNames.add(FileUtils.getName(fileName)); newFileNames.add(FileUtils.getName(fileName));
originalFilenames.add(file.getOriginalFilename()); originalFilenames.add(file.getOriginalFilename());
} }
AjaxResult ajax = AjaxResult.success(); AjaxResult ajax = AjaxResult.success();
ajax.put("urls", StringUtils.join(urls, FILE_DELIMITER)); ajax.put("urls", StringUtils.join(urls, FILE_DELIMITER));
ajax.put("fileNames", StringUtils.join(fileNames, FILE_DELIMITER)); ajax.put("fileNames", StringUtils.join(fileNames, FILE_DELIMITER));
ajax.put("newFileNames", StringUtils.join(newFileNames, FILE_DELIMITER)); ajax.put("newFileNames", StringUtils.join(newFileNames, FILE_DELIMITER));
ajax.put("originalFilenames", StringUtils.join(originalFilenames, FILE_DELIMITER)); ajax.put("originalFilenames", StringUtils.join(originalFilenames, FILE_DELIMITER));
return ajax; return ajax;
} }
catch (Exception e) catch (Exception e)
{ {
return AjaxResult.error(e.getMessage()); return AjaxResult.error(e.getMessage());
} }
} }
/** /**
* 本地资源通用下载 * 本地资源通用下载
*/ */
@GetMapping("/download/resource") @GetMapping("/download/resource")
public void resourceDownload(String resource, HttpServletRequest request, HttpServletResponse response) public void resourceDownload(String resource, HttpServletRequest request, HttpServletResponse response)
throws Exception throws Exception
{ {
try try
{ {
if (!FileUtils.checkAllowDownload(resource)) if (!FileUtils.checkAllowDownload(resource))
{ {
throw new Exception(StringUtils.format("资源文件({})非法,不允许下载。 ", resource)); throw new Exception(StringUtils.format("资源文件({})非法,不允许下载。 ", resource));
} }
// 本地资源路径 // 本地资源路径
String localPath = RuoYiConfig.getProfile(); String localPath = RuoYiConfig.getProfile();
// 数据库资源地址 // 数据库资源地址
String downloadPath = localPath + FileUtils.stripPrefix(resource); String downloadPath = localPath + FileUtils.stripPrefix(resource);
// 下载名称 // 下载名称
String downloadName = StringUtils.substringAfterLast(downloadPath, "/"); String downloadName = StringUtils.substringAfterLast(downloadPath, "/");
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE); response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
FileUtils.setAttachmentResponseHeader(response, downloadName); FileUtils.setAttachmentResponseHeader(response, downloadName);
FileUtils.writeBytes(downloadPath, response.getOutputStream()); FileUtils.writeBytes(downloadPath, response.getOutputStream());
} }
catch (Exception e) catch (Exception e)
{ {
log.error("下载文件失败", e); log.error("下载文件失败", e);
} }
} }
} }

View File

@@ -7,6 +7,13 @@ 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;
@@ -15,33 +22,24 @@ 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 final static List<SysCache> caches = new ArrayList<SysCache>(); private static final 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)
@@ -55,23 +53,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.cacheType()); info.put("cache_type", stats.getCacheType());
info.put("cache_mode", stats.mode()); info.put("cache_mode", stats.getMode());
info.put("key_size", stats.keySize()); info.put("key_size", stats.getKeySize());
info.put("hit_count", stats.hitCount()); info.put("hit_count", stats.getHitCount());
info.put("miss_count", stats.missCount()); info.put("miss_count", stats.getMissCount());
info.put("expired_count", stats.expiredCount()); info.put("expired_count", stats.getExpiredCount());
info.put("write_count", stats.writeCount()); info.put("write_count", stats.getWriteCount());
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.keySize()); result.put("dbSize", stats.getKeySize());
List<Map<String, String>> pieList = new ArrayList<>(); List<Map<String, String>> pieList = new ArrayList<>();
pieList.add(statEntry("hit_count", stats.hitCount())); pieList.add(statEntry("hit_count", stats.getHitCount()));
pieList.add(statEntry("miss_count", stats.missCount())); pieList.add(statEntry("miss_count", stats.getMissCount()));
pieList.add(statEntry("expired_count", stats.expiredCount())); pieList.add(statEntry("expired_count", stats.getExpiredCount()));
pieList.add(statEntry("write_count", stats.writeCount())); pieList.add(statEntry("write_count", stats.getWriteCount()));
result.put("commandStats", pieList); result.put("commandStats", pieList);
return AjaxResult.success(result); return AjaxResult.success(result);
} }
@@ -80,7 +78,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')")
@@ -139,9 +137,9 @@ public class CacheController
{ {
return StringUtils.EMPTY; return StringUtils.EMPTY;
} }
if (cacheValue instanceof String stringValue) if (cacheValue instanceof String)
{ {
return stringValue; return (String) cacheValue;
} }
return JSON.toJSONString(cacheValue); return JSON.toJSONString(cacheValue);
} }

View File

@@ -1,27 +1,27 @@
package com.ruoyi.web.controller.monitor; package com.ruoyi.web.controller.monitor;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
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.core.domain.AjaxResult; import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.framework.web.domain.Server; import com.ruoyi.framework.web.domain.Server;
/** /**
* 服务器监控 * 服务器监控
* *
* @author ruoyi * @author ruoyi
*/ */
@RestController @RestController
@RequestMapping("/monitor/server") @RequestMapping("/monitor/server")
public class ServerController public class ServerController
{ {
@PreAuthorize("@ss.hasPermi('monitor:server:list')") @PreAuthorize("@ss.hasPermi('monitor:server:list')")
@GetMapping() @GetMapping()
public AjaxResult getInfo() throws Exception public AjaxResult getInfo() throws Exception
{ {
Server server = new Server(); Server server = new Server();
server.copyTo(); server.copyTo();
return AjaxResult.success(server); return AjaxResult.success(server);
} }
} }

View File

@@ -1,82 +1,82 @@
package com.ruoyi.web.controller.monitor; package com.ruoyi.web.controller.monitor;
import java.util.List; import java.util.List;
import jakarta.servlet.http.HttpServletResponse; import javax.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;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
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.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.enums.BusinessType; import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.framework.web.service.SysPasswordService; import com.ruoyi.framework.web.service.SysPasswordService;
import com.ruoyi.system.domain.SysLogininfor; import com.ruoyi.system.domain.SysLogininfor;
import com.ruoyi.system.service.ISysLogininforService; import com.ruoyi.system.service.ISysLogininforService;
/** /**
* 系统访问记录 * 系统访问记录
* *
* @author ruoyi * @author ruoyi
*/ */
@RestController @RestController
@RequestMapping("/monitor/logininfor") @RequestMapping("/monitor/logininfor")
public class SysLogininforController extends BaseController public class SysLogininforController extends BaseController
{ {
@Autowired @Autowired
private ISysLogininforService logininforService; private ISysLogininforService logininforService;
@Autowired @Autowired
private SysPasswordService passwordService; private SysPasswordService passwordService;
@PreAuthorize("@ss.hasPermi('monitor:logininfor:list')") @PreAuthorize("@ss.hasPermi('monitor:logininfor:list')")
@GetMapping("/list") @GetMapping("/list")
public TableDataInfo list(SysLogininfor logininfor) public TableDataInfo list(SysLogininfor logininfor)
{ {
startPage(); startPage();
List<SysLogininfor> list = logininforService.selectLogininforList(logininfor); List<SysLogininfor> list = logininforService.selectLogininforList(logininfor);
return getDataTable(list); return getDataTable(list);
} }
@Log(title = "登录日志", businessType = BusinessType.EXPORT) @Log(title = "登录日志", businessType = BusinessType.EXPORT)
@PreAuthorize("@ss.hasPermi('monitor:logininfor:export')") @PreAuthorize("@ss.hasPermi('monitor:logininfor:export')")
@PostMapping("/export") @PostMapping("/export")
public void export(HttpServletResponse response, SysLogininfor logininfor) public void export(HttpServletResponse response, SysLogininfor logininfor)
{ {
List<SysLogininfor> list = logininforService.selectLogininforList(logininfor); List<SysLogininfor> list = logininforService.selectLogininforList(logininfor);
ExcelUtil<SysLogininfor> util = new ExcelUtil<SysLogininfor>(SysLogininfor.class); ExcelUtil<SysLogininfor> util = new ExcelUtil<SysLogininfor>(SysLogininfor.class);
util.exportExcel(response, list, "登录日志"); util.exportExcel(response, list, "登录日志");
} }
@PreAuthorize("@ss.hasPermi('monitor:logininfor:remove')") @PreAuthorize("@ss.hasPermi('monitor:logininfor:remove')")
@Log(title = "登录日志", businessType = BusinessType.DELETE) @Log(title = "登录日志", businessType = BusinessType.DELETE)
@DeleteMapping("/{infoIds}") @DeleteMapping("/{infoIds}")
public AjaxResult remove(@PathVariable Long[] infoIds) public AjaxResult remove(@PathVariable Long[] infoIds)
{ {
return toAjax(logininforService.deleteLogininforByIds(infoIds)); return toAjax(logininforService.deleteLogininforByIds(infoIds));
} }
@PreAuthorize("@ss.hasPermi('monitor:logininfor:remove')") @PreAuthorize("@ss.hasPermi('monitor:logininfor:remove')")
@Log(title = "登录日志", businessType = BusinessType.CLEAN) @Log(title = "登录日志", businessType = BusinessType.CLEAN)
@DeleteMapping("/clean") @DeleteMapping("/clean")
public AjaxResult clean() public AjaxResult clean()
{ {
logininforService.cleanLogininfor(); logininforService.cleanLogininfor();
return success(); return success();
} }
@PreAuthorize("@ss.hasPermi('monitor:logininfor:unlock')") @PreAuthorize("@ss.hasPermi('monitor:logininfor:unlock')")
@Log(title = "账户解锁", businessType = BusinessType.OTHER) @Log(title = "账户解锁", businessType = BusinessType.OTHER)
@GetMapping("/unlock/{userName}") @GetMapping("/unlock/{userName}")
public AjaxResult unlock(@PathVariable("userName") String userName) public AjaxResult unlock(@PathVariable("userName") String userName)
{ {
passwordService.clearLoginRecordCache(userName); passwordService.clearLoginRecordCache(userName);
return success(); return success();
} }
} }

View File

@@ -1,69 +1,69 @@
package com.ruoyi.web.controller.monitor; package com.ruoyi.web.controller.monitor;
import java.util.List; import java.util.List;
import jakarta.servlet.http.HttpServletResponse; import javax.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;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
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.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.enums.BusinessType; import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.system.domain.SysOperLog; import com.ruoyi.system.domain.SysOperLog;
import com.ruoyi.system.service.ISysOperLogService; import com.ruoyi.system.service.ISysOperLogService;
/** /**
* 操作日志记录 * 操作日志记录
* *
* @author ruoyi * @author ruoyi
*/ */
@RestController @RestController
@RequestMapping("/monitor/operlog") @RequestMapping("/monitor/operlog")
public class SysOperlogController extends BaseController public class SysOperlogController extends BaseController
{ {
@Autowired @Autowired
private ISysOperLogService operLogService; private ISysOperLogService operLogService;
@PreAuthorize("@ss.hasPermi('monitor:operlog:list')") @PreAuthorize("@ss.hasPermi('monitor:operlog:list')")
@GetMapping("/list") @GetMapping("/list")
public TableDataInfo list(SysOperLog operLog) public TableDataInfo list(SysOperLog operLog)
{ {
startPage(); startPage();
List<SysOperLog> list = operLogService.selectOperLogList(operLog); List<SysOperLog> list = operLogService.selectOperLogList(operLog);
return getDataTable(list); return getDataTable(list);
} }
@Log(title = "操作日志", businessType = BusinessType.EXPORT) @Log(title = "操作日志", businessType = BusinessType.EXPORT)
@PreAuthorize("@ss.hasPermi('monitor:operlog:export')") @PreAuthorize("@ss.hasPermi('monitor:operlog:export')")
@PostMapping("/export") @PostMapping("/export")
public void export(HttpServletResponse response, SysOperLog operLog) public void export(HttpServletResponse response, SysOperLog operLog)
{ {
List<SysOperLog> list = operLogService.selectOperLogList(operLog); List<SysOperLog> list = operLogService.selectOperLogList(operLog);
ExcelUtil<SysOperLog> util = new ExcelUtil<SysOperLog>(SysOperLog.class); ExcelUtil<SysOperLog> util = new ExcelUtil<SysOperLog>(SysOperLog.class);
util.exportExcel(response, list, "操作日志"); util.exportExcel(response, list, "操作日志");
} }
@Log(title = "操作日志", businessType = BusinessType.DELETE) @Log(title = "操作日志", businessType = BusinessType.DELETE)
@PreAuthorize("@ss.hasPermi('monitor:operlog:remove')") @PreAuthorize("@ss.hasPermi('monitor:operlog:remove')")
@DeleteMapping("/{operIds}") @DeleteMapping("/{operIds}")
public AjaxResult remove(@PathVariable Long[] operIds) public AjaxResult remove(@PathVariable Long[] operIds)
{ {
return toAjax(operLogService.deleteOperLogByIds(operIds)); return toAjax(operLogService.deleteOperLogByIds(operIds));
} }
@Log(title = "操作日志", businessType = BusinessType.CLEAN) @Log(title = "操作日志", businessType = BusinessType.CLEAN)
@PreAuthorize("@ss.hasPermi('monitor:operlog:remove')") @PreAuthorize("@ss.hasPermi('monitor:operlog:remove')")
@DeleteMapping("/clean") @DeleteMapping("/clean")
public AjaxResult clean() public AjaxResult clean()
{ {
operLogService.cleanOperLog(); operLogService.cleanOperLog();
return success(); return success();
} }
} }

View File

@@ -1,83 +1,83 @@
package com.ruoyi.web.controller.monitor; package com.ruoyi.web.controller.monitor;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
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;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
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.annotation.Log; import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.constant.CacheConstants; import com.ruoyi.common.constant.CacheConstants;
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.domain.model.LoginUser; import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.redis.RedisCache; import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.SysUserOnline; import com.ruoyi.system.domain.SysUserOnline;
import com.ruoyi.system.service.ISysUserOnlineService; import com.ruoyi.system.service.ISysUserOnlineService;
/** /**
* 在线用户监控 * 在线用户监控
* *
* @author ruoyi * @author ruoyi
*/ */
@RestController @RestController
@RequestMapping("/monitor/online") @RequestMapping("/monitor/online")
public class SysUserOnlineController extends BaseController public class SysUserOnlineController extends BaseController
{ {
@Autowired @Autowired
private ISysUserOnlineService userOnlineService; private ISysUserOnlineService userOnlineService;
@Autowired @Autowired
private RedisCache redisCache; private RedisCache redisCache;
@PreAuthorize("@ss.hasPermi('monitor:online:list')") @PreAuthorize("@ss.hasPermi('monitor:online:list')")
@GetMapping("/list") @GetMapping("/list")
public TableDataInfo list(String ipaddr, String userName) public TableDataInfo list(String ipaddr, String userName)
{ {
Collection<String> keys = redisCache.keys(CacheConstants.LOGIN_TOKEN_KEY + "*"); Collection<String> keys = redisCache.keys(CacheConstants.LOGIN_TOKEN_KEY + "*");
List<SysUserOnline> userOnlineList = new ArrayList<SysUserOnline>(); List<SysUserOnline> userOnlineList = new ArrayList<SysUserOnline>();
for (String key : keys) for (String key : keys)
{ {
LoginUser user = redisCache.getCacheObject(key); LoginUser user = redisCache.getCacheObject(key);
if (StringUtils.isNotEmpty(ipaddr) && StringUtils.isNotEmpty(userName)) if (StringUtils.isNotEmpty(ipaddr) && StringUtils.isNotEmpty(userName))
{ {
userOnlineList.add(userOnlineService.selectOnlineByInfo(ipaddr, userName, user)); userOnlineList.add(userOnlineService.selectOnlineByInfo(ipaddr, userName, user));
} }
else if (StringUtils.isNotEmpty(ipaddr)) else if (StringUtils.isNotEmpty(ipaddr))
{ {
userOnlineList.add(userOnlineService.selectOnlineByIpaddr(ipaddr, user)); userOnlineList.add(userOnlineService.selectOnlineByIpaddr(ipaddr, user));
} }
else if (StringUtils.isNotEmpty(userName) && StringUtils.isNotNull(user.getUser())) else if (StringUtils.isNotEmpty(userName) && StringUtils.isNotNull(user.getUser()))
{ {
userOnlineList.add(userOnlineService.selectOnlineByUserName(userName, user)); userOnlineList.add(userOnlineService.selectOnlineByUserName(userName, user));
} }
else else
{ {
userOnlineList.add(userOnlineService.loginUserToUserOnline(user)); userOnlineList.add(userOnlineService.loginUserToUserOnline(user));
} }
} }
Collections.reverse(userOnlineList); Collections.reverse(userOnlineList);
userOnlineList.removeAll(Collections.singleton(null)); userOnlineList.removeAll(Collections.singleton(null));
return getDataTable(userOnlineList); return getDataTable(userOnlineList);
} }
/** /**
* 强退用户 * 强退用户
*/ */
@PreAuthorize("@ss.hasPermi('monitor:online:forceLogout')") @PreAuthorize("@ss.hasPermi('monitor:online:forceLogout')")
@Log(title = "在线用户", businessType = BusinessType.FORCE) @Log(title = "在线用户", businessType = BusinessType.FORCE)
@DeleteMapping("/{tokenId}") @DeleteMapping("/{tokenId}")
public AjaxResult forceLogout(@PathVariable String tokenId) public AjaxResult forceLogout(@PathVariable String tokenId)
{ {
redisCache.deleteObject(CacheConstants.LOGIN_TOKEN_KEY + tokenId); redisCache.deleteObject(CacheConstants.LOGIN_TOKEN_KEY + tokenId);
return success(); return success();
} }
} }

View File

@@ -1,133 +1,133 @@
package com.ruoyi.web.controller.system; package com.ruoyi.web.controller.system;
import java.util.List; import java.util.List;
import jakarta.servlet.http.HttpServletResponse; import javax.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;
import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping; 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.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.enums.BusinessType; import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.system.domain.SysConfig; import com.ruoyi.system.domain.SysConfig;
import com.ruoyi.system.service.ISysConfigService; import com.ruoyi.system.service.ISysConfigService;
/** /**
* 参数配置 信息操作处理 * 参数配置 信息操作处理
* *
* @author ruoyi * @author ruoyi
*/ */
@RestController @RestController
@RequestMapping("/system/config") @RequestMapping("/system/config")
public class SysConfigController extends BaseController public class SysConfigController extends BaseController
{ {
@Autowired @Autowired
private ISysConfigService configService; private ISysConfigService configService;
/** /**
* 获取参数配置列表 * 获取参数配置列表
*/ */
@PreAuthorize("@ss.hasPermi('system:config:list')") @PreAuthorize("@ss.hasPermi('system:config:list')")
@GetMapping("/list") @GetMapping("/list")
public TableDataInfo list(SysConfig config) public TableDataInfo list(SysConfig config)
{ {
startPage(); startPage();
List<SysConfig> list = configService.selectConfigList(config); List<SysConfig> list = configService.selectConfigList(config);
return getDataTable(list); return getDataTable(list);
} }
@Log(title = "参数管理", businessType = BusinessType.EXPORT) @Log(title = "参数管理", businessType = BusinessType.EXPORT)
@PreAuthorize("@ss.hasPermi('system:config:export')") @PreAuthorize("@ss.hasPermi('system:config:export')")
@PostMapping("/export") @PostMapping("/export")
public void export(HttpServletResponse response, SysConfig config) public void export(HttpServletResponse response, SysConfig config)
{ {
List<SysConfig> list = configService.selectConfigList(config); List<SysConfig> list = configService.selectConfigList(config);
ExcelUtil<SysConfig> util = new ExcelUtil<SysConfig>(SysConfig.class); ExcelUtil<SysConfig> util = new ExcelUtil<SysConfig>(SysConfig.class);
util.exportExcel(response, list, "参数数据"); util.exportExcel(response, list, "参数数据");
} }
/** /**
* 根据参数编号获取详细信息 * 根据参数编号获取详细信息
*/ */
@PreAuthorize("@ss.hasPermi('system:config:query')") @PreAuthorize("@ss.hasPermi('system:config:query')")
@GetMapping(value = "/{configId}") @GetMapping(value = "/{configId}")
public AjaxResult getInfo(@PathVariable Long configId) public AjaxResult getInfo(@PathVariable Long configId)
{ {
return success(configService.selectConfigById(configId)); return success(configService.selectConfigById(configId));
} }
/** /**
* 根据参数键名查询参数值 * 根据参数键名查询参数值
*/ */
@GetMapping(value = "/configKey/{configKey}") @GetMapping(value = "/configKey/{configKey}")
public AjaxResult getConfigKey(@PathVariable String configKey) public AjaxResult getConfigKey(@PathVariable String configKey)
{ {
return success(configService.selectConfigByKey(configKey)); return success(configService.selectConfigByKey(configKey));
} }
/** /**
* 新增参数配置 * 新增参数配置
*/ */
@PreAuthorize("@ss.hasPermi('system:config:add')") @PreAuthorize("@ss.hasPermi('system:config:add')")
@Log(title = "参数管理", businessType = BusinessType.INSERT) @Log(title = "参数管理", businessType = BusinessType.INSERT)
@PostMapping @PostMapping
public AjaxResult add(@Validated @RequestBody SysConfig config) public AjaxResult add(@Validated @RequestBody SysConfig config)
{ {
if (!configService.checkConfigKeyUnique(config)) if (!configService.checkConfigKeyUnique(config))
{ {
return error("新增参数'" + config.getConfigName() + "'失败,参数键名已存在"); return error("新增参数'" + config.getConfigName() + "'失败,参数键名已存在");
} }
config.setCreateBy(getUsername()); config.setCreateBy(getUsername());
return toAjax(configService.insertConfig(config)); return toAjax(configService.insertConfig(config));
} }
/** /**
* 修改参数配置 * 修改参数配置
*/ */
@PreAuthorize("@ss.hasPermi('system:config:edit')") @PreAuthorize("@ss.hasPermi('system:config:edit')")
@Log(title = "参数管理", businessType = BusinessType.UPDATE) @Log(title = "参数管理", businessType = BusinessType.UPDATE)
@PutMapping @PutMapping
public AjaxResult edit(@Validated @RequestBody SysConfig config) public AjaxResult edit(@Validated @RequestBody SysConfig config)
{ {
if (!configService.checkConfigKeyUnique(config)) if (!configService.checkConfigKeyUnique(config))
{ {
return error("修改参数'" + config.getConfigName() + "'失败,参数键名已存在"); return error("修改参数'" + config.getConfigName() + "'失败,参数键名已存在");
} }
config.setUpdateBy(getUsername()); config.setUpdateBy(getUsername());
return toAjax(configService.updateConfig(config)); return toAjax(configService.updateConfig(config));
} }
/** /**
* 删除参数配置 * 删除参数配置
*/ */
@PreAuthorize("@ss.hasPermi('system:config:remove')") @PreAuthorize("@ss.hasPermi('system:config:remove')")
@Log(title = "参数管理", businessType = BusinessType.DELETE) @Log(title = "参数管理", businessType = BusinessType.DELETE)
@DeleteMapping("/{configIds}") @DeleteMapping("/{configIds}")
public AjaxResult remove(@PathVariable Long[] configIds) public AjaxResult remove(@PathVariable Long[] configIds)
{ {
configService.deleteConfigByIds(configIds); configService.deleteConfigByIds(configIds);
return success(); return success();
} }
/** /**
* 刷新参数缓存 * 刷新参数缓存
*/ */
@PreAuthorize("@ss.hasPermi('system:config:remove')") @PreAuthorize("@ss.hasPermi('system:config:remove')")
@Log(title = "参数管理", businessType = BusinessType.CLEAN) @Log(title = "参数管理", businessType = BusinessType.CLEAN)
@DeleteMapping("/refreshCache") @DeleteMapping("/refreshCache")
public AjaxResult refreshCache() public AjaxResult refreshCache()
{ {
configService.resetConfigCache(); configService.resetConfigCache();
return success(); return success();
} }
} }

View File

@@ -1,132 +1,147 @@
package com.ruoyi.web.controller.system; package com.ruoyi.web.controller.system;
import java.util.List; import java.util.List;
import org.apache.commons.lang3.ArrayUtils; import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired; import org.apache.commons.lang3.ArrayUtils;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated; import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RequestMapping;
import com.ruoyi.common.annotation.Log; import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.constant.UserConstants; import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController; import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.entity.SysDept; import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.system.service.ISysDeptService; import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.service.ISysDeptService;
/**
* 部门信息 /**
* * 部门信息
* @author ruoyi *
*/ * @author ruoyi
@RestController */
@RequestMapping("/system/dept") @RestController
public class SysDeptController extends BaseController @RequestMapping("/system/dept")
{ public class SysDeptController extends BaseController
@Autowired {
private ISysDeptService deptService; @Autowired
private ISysDeptService deptService;
/**
* 获取部门列表 /**
*/ * 获取部门列表
@PreAuthorize("@ss.hasPermi('system:dept:list')") */
@GetMapping("/list") @PreAuthorize("@ss.hasPermi('system:dept:list')")
public AjaxResult list(SysDept dept) @GetMapping("/list")
{ public AjaxResult list(SysDept dept)
List<SysDept> depts = deptService.selectDeptList(dept); {
return success(depts); List<SysDept> depts = deptService.selectDeptList(dept);
} return success(depts);
}
/**
* 查询部门列表(排除节点) /**
*/ * 查询部门列表(排除节点)
@PreAuthorize("@ss.hasPermi('system:dept:list')") */
@GetMapping("/list/exclude/{deptId}") @PreAuthorize("@ss.hasPermi('system:dept:list')")
public AjaxResult excludeChild(@PathVariable(value = "deptId", required = false) Long deptId) @GetMapping("/list/exclude/{deptId}")
{ public AjaxResult excludeChild(@PathVariable(value = "deptId", required = false) Long deptId)
List<SysDept> depts = deptService.selectDeptList(new SysDept()); {
depts.removeIf(d -> d.getDeptId().intValue() == deptId || ArrayUtils.contains(StringUtils.split(d.getAncestors(), ","), deptId + "")); List<SysDept> depts = deptService.selectDeptList(new SysDept());
return success(depts); depts.removeIf(d -> d.getDeptId().intValue() == deptId || ArrayUtils.contains(StringUtils.split(d.getAncestors(), ","), deptId + ""));
} return success(depts);
}
/**
* 根据部门编号获取详细信息 /**
*/ * 根据部门编号获取详细信息
@PreAuthorize("@ss.hasPermi('system:dept:query')") */
@GetMapping(value = "/{deptId}") @PreAuthorize("@ss.hasPermi('system:dept:query')")
public AjaxResult getInfo(@PathVariable Long deptId) @GetMapping(value = "/{deptId}")
{ public AjaxResult getInfo(@PathVariable Long deptId)
deptService.checkDeptDataScope(deptId); {
return success(deptService.selectDeptById(deptId)); deptService.checkDeptDataScope(deptId);
} return success(deptService.selectDeptById(deptId));
}
/**
* 新增部门 /**
*/ * 新增部门
@PreAuthorize("@ss.hasPermi('system:dept:add')") */
@Log(title = "部门管理", businessType = BusinessType.INSERT) @PreAuthorize("@ss.hasPermi('system:dept:add')")
@PostMapping @Log(title = "部门管理", businessType = BusinessType.INSERT)
public AjaxResult add(@Validated @RequestBody SysDept dept) @PostMapping
{ public AjaxResult add(@Validated @RequestBody SysDept dept)
if (!deptService.checkDeptNameUnique(dept)) {
{ if (!deptService.checkDeptNameUnique(dept))
return error("新增部门'" + dept.getDeptName() + "'失败,部门名称已存在"); {
} return error("新增部门'" + dept.getDeptName() + "'失败,部门名称已存在");
dept.setCreateBy(getUsername()); }
return toAjax(deptService.insertDept(dept)); dept.setCreateBy(getUsername());
} return toAjax(deptService.insertDept(dept));
}
/**
* 修改部门 /**
*/ * 修改部门
@PreAuthorize("@ss.hasPermi('system:dept:edit')") */
@Log(title = "部门管理", businessType = BusinessType.UPDATE) @PreAuthorize("@ss.hasPermi('system:dept:edit')")
@PutMapping @Log(title = "部门管理", businessType = BusinessType.UPDATE)
public AjaxResult edit(@Validated @RequestBody SysDept dept) @PutMapping
{ public AjaxResult edit(@Validated @RequestBody SysDept dept)
Long deptId = dept.getDeptId(); {
deptService.checkDeptDataScope(deptId); Long deptId = dept.getDeptId();
if (!deptService.checkDeptNameUnique(dept)) deptService.checkDeptDataScope(deptId);
{ if (!deptService.checkDeptNameUnique(dept))
return error("修改部门'" + dept.getDeptName() + "'失败,部门名称已存在"); {
} return error("修改部门'" + dept.getDeptName() + "'失败,部门名称已存在");
else if (dept.getParentId().equals(deptId)) }
{ else if (dept.getParentId().equals(deptId))
return error("修改部门'" + dept.getDeptName() + "'失败,上级部门不能是自己"); {
} return error("修改部门'" + dept.getDeptName() + "'失败,上级部门不能是自己");
else if (StringUtils.equals(UserConstants.DEPT_DISABLE, dept.getStatus()) && deptService.selectNormalChildrenDeptById(deptId) > 0) }
{ else if (StringUtils.equals(UserConstants.DEPT_DISABLE, dept.getStatus()) && deptService.selectNormalChildrenDeptById(deptId) > 0)
return error("该部门包含未停用的子部门!"); {
} return error("该部门包含未停用的子部门!");
dept.setUpdateBy(getUsername()); }
return toAjax(deptService.updateDept(dept)); dept.setUpdateBy(getUsername());
} return toAjax(deptService.updateDept(dept));
}
/**
* 删除部门 /**
*/ * 保存部门排序
@PreAuthorize("@ss.hasPermi('system:dept:remove')") */
@Log(title = "部门管理", businessType = BusinessType.DELETE) @PreAuthorize("@ss.hasPermi('system:dept:edit')")
@DeleteMapping("/{deptId}") @Log(title = "保存部门排序", businessType = BusinessType.UPDATE)
public AjaxResult remove(@PathVariable Long deptId) @PutMapping("/updateSort")
{ public AjaxResult updateSort(@RequestBody Map<String, String> params)
if (deptService.hasChildByDeptId(deptId)) {
{ String[] deptIds = params.get("deptIds").split(",");
return warn("存在下级部门,不允许删除"); String[] orderNums = params.get("orderNums").split(",");
} deptService.updateDeptSort(deptIds, orderNums);
if (deptService.checkDeptExistUser(deptId)) return success();
{ }
return warn("部门存在用户,不允许删除");
} /**
deptService.checkDeptDataScope(deptId); * 删除部门
return toAjax(deptService.deleteDeptById(deptId)); */
} @PreAuthorize("@ss.hasPermi('system:dept:remove')")
} @Log(title = "部门管理", businessType = BusinessType.DELETE)
@DeleteMapping("/{deptId}")
public AjaxResult remove(@PathVariable Long deptId)
{
if (deptService.hasChildByDeptId(deptId))
{
return warn("存在下级部门,不允许删除");
}
if (deptService.checkDeptExistUser(deptId))
{
return warn("部门存在用户,不允许删除");
}
deptService.checkDeptDataScope(deptId);
return toAjax(deptService.deleteDeptById(deptId));
}
}

View File

@@ -1,121 +1,121 @@
package com.ruoyi.web.controller.system; package com.ruoyi.web.controller.system;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import jakarta.servlet.http.HttpServletResponse; import javax.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;
import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping; 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.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.domain.entity.SysDictData; import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.enums.BusinessType;
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.system.service.ISysDictDataService; import com.ruoyi.system.service.ISysDictDataService;
import com.ruoyi.system.service.ISysDictTypeService; import com.ruoyi.system.service.ISysDictTypeService;
/** /**
* 数据字典信息 * 数据字典信息
* *
* @author ruoyi * @author ruoyi
*/ */
@RestController @RestController
@RequestMapping("/system/dict/data") @RequestMapping("/system/dict/data")
public class SysDictDataController extends BaseController public class SysDictDataController extends BaseController
{ {
@Autowired @Autowired
private ISysDictDataService dictDataService; private ISysDictDataService dictDataService;
@Autowired @Autowired
private ISysDictTypeService dictTypeService; private ISysDictTypeService dictTypeService;
@PreAuthorize("@ss.hasPermi('system:dict:list')") @PreAuthorize("@ss.hasPermi('system:dict:list')")
@GetMapping("/list") @GetMapping("/list")
public TableDataInfo list(SysDictData dictData) public TableDataInfo list(SysDictData dictData)
{ {
startPage(); startPage();
List<SysDictData> list = dictDataService.selectDictDataList(dictData); List<SysDictData> list = dictDataService.selectDictDataList(dictData);
return getDataTable(list); return getDataTable(list);
} }
@Log(title = "字典数据", businessType = BusinessType.EXPORT) @Log(title = "字典数据", businessType = BusinessType.EXPORT)
@PreAuthorize("@ss.hasPermi('system:dict:export')") @PreAuthorize("@ss.hasPermi('system:dict:export')")
@PostMapping("/export") @PostMapping("/export")
public void export(HttpServletResponse response, SysDictData dictData) public void export(HttpServletResponse response, SysDictData dictData)
{ {
List<SysDictData> list = dictDataService.selectDictDataList(dictData); List<SysDictData> list = dictDataService.selectDictDataList(dictData);
ExcelUtil<SysDictData> util = new ExcelUtil<SysDictData>(SysDictData.class); ExcelUtil<SysDictData> util = new ExcelUtil<SysDictData>(SysDictData.class);
util.exportExcel(response, list, "字典数据"); util.exportExcel(response, list, "字典数据");
} }
/** /**
* 查询字典数据详细 * 查询字典数据详细
*/ */
@PreAuthorize("@ss.hasPermi('system:dict:query')") @PreAuthorize("@ss.hasPermi('system:dict:query')")
@GetMapping(value = "/{dictCode}") @GetMapping(value = "/{dictCode}")
public AjaxResult getInfo(@PathVariable Long dictCode) public AjaxResult getInfo(@PathVariable Long dictCode)
{ {
return success(dictDataService.selectDictDataById(dictCode)); return success(dictDataService.selectDictDataById(dictCode));
} }
/** /**
* 根据字典类型查询字典数据信息 * 根据字典类型查询字典数据信息
*/ */
@GetMapping(value = "/type/{dictType}") @GetMapping(value = "/type/{dictType}")
public AjaxResult dictType(@PathVariable String dictType) public AjaxResult dictType(@PathVariable String dictType)
{ {
List<SysDictData> data = dictTypeService.selectDictDataByType(dictType); List<SysDictData> data = dictTypeService.selectDictDataByType(dictType);
if (StringUtils.isNull(data)) if (StringUtils.isNull(data))
{ {
data = new ArrayList<SysDictData>(); data = new ArrayList<SysDictData>();
} }
return success(data); return success(data);
} }
/** /**
* 新增字典类型 * 新增字典类型
*/ */
@PreAuthorize("@ss.hasPermi('system:dict:add')") @PreAuthorize("@ss.hasPermi('system:dict:add')")
@Log(title = "字典数据", businessType = BusinessType.INSERT) @Log(title = "字典数据", businessType = BusinessType.INSERT)
@PostMapping @PostMapping
public AjaxResult add(@Validated @RequestBody SysDictData dict) public AjaxResult add(@Validated @RequestBody SysDictData dict)
{ {
dict.setCreateBy(getUsername()); dict.setCreateBy(getUsername());
return toAjax(dictDataService.insertDictData(dict)); return toAjax(dictDataService.insertDictData(dict));
} }
/** /**
* 修改保存字典类型 * 修改保存字典类型
*/ */
@PreAuthorize("@ss.hasPermi('system:dict:edit')") @PreAuthorize("@ss.hasPermi('system:dict:edit')")
@Log(title = "字典数据", businessType = BusinessType.UPDATE) @Log(title = "字典数据", businessType = BusinessType.UPDATE)
@PutMapping @PutMapping
public AjaxResult edit(@Validated @RequestBody SysDictData dict) public AjaxResult edit(@Validated @RequestBody SysDictData dict)
{ {
dict.setUpdateBy(getUsername()); dict.setUpdateBy(getUsername());
return toAjax(dictDataService.updateDictData(dict)); return toAjax(dictDataService.updateDictData(dict));
} }
/** /**
* 删除字典类型 * 删除字典类型
*/ */
@PreAuthorize("@ss.hasPermi('system:dict:remove')") @PreAuthorize("@ss.hasPermi('system:dict:remove')")
@Log(title = "字典类型", businessType = BusinessType.DELETE) @Log(title = "字典类型", businessType = BusinessType.DELETE)
@DeleteMapping("/{dictCodes}") @DeleteMapping("/{dictCodes}")
public AjaxResult remove(@PathVariable Long[] dictCodes) public AjaxResult remove(@PathVariable Long[] dictCodes)
{ {
dictDataService.deleteDictDataByIds(dictCodes); dictDataService.deleteDictDataByIds(dictCodes);
return success(); return success();
} }
} }

View File

@@ -1,131 +1,131 @@
package com.ruoyi.web.controller.system; package com.ruoyi.web.controller.system;
import java.util.List; import java.util.List;
import jakarta.servlet.http.HttpServletResponse; import javax.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;
import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping; 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.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.domain.entity.SysDictType; import com.ruoyi.common.core.domain.entity.SysDictType;
import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.system.service.ISysDictTypeService; import com.ruoyi.system.service.ISysDictTypeService;
/** /**
* 数据字典信息 * 数据字典信息
* *
* @author ruoyi * @author ruoyi
*/ */
@RestController @RestController
@RequestMapping("/system/dict/type") @RequestMapping("/system/dict/type")
public class SysDictTypeController extends BaseController public class SysDictTypeController extends BaseController
{ {
@Autowired @Autowired
private ISysDictTypeService dictTypeService; private ISysDictTypeService dictTypeService;
@PreAuthorize("@ss.hasPermi('system:dict:list')") @PreAuthorize("@ss.hasPermi('system:dict:list')")
@GetMapping("/list") @GetMapping("/list")
public TableDataInfo list(SysDictType dictType) public TableDataInfo list(SysDictType dictType)
{ {
startPage(); startPage();
List<SysDictType> list = dictTypeService.selectDictTypeList(dictType); List<SysDictType> list = dictTypeService.selectDictTypeList(dictType);
return getDataTable(list); return getDataTable(list);
} }
@Log(title = "字典类型", businessType = BusinessType.EXPORT) @Log(title = "字典类型", businessType = BusinessType.EXPORT)
@PreAuthorize("@ss.hasPermi('system:dict:export')") @PreAuthorize("@ss.hasPermi('system:dict:export')")
@PostMapping("/export") @PostMapping("/export")
public void export(HttpServletResponse response, SysDictType dictType) public void export(HttpServletResponse response, SysDictType dictType)
{ {
List<SysDictType> list = dictTypeService.selectDictTypeList(dictType); List<SysDictType> list = dictTypeService.selectDictTypeList(dictType);
ExcelUtil<SysDictType> util = new ExcelUtil<SysDictType>(SysDictType.class); ExcelUtil<SysDictType> util = new ExcelUtil<SysDictType>(SysDictType.class);
util.exportExcel(response, list, "字典类型"); util.exportExcel(response, list, "字典类型");
} }
/** /**
* 查询字典类型详细 * 查询字典类型详细
*/ */
@PreAuthorize("@ss.hasPermi('system:dict:query')") @PreAuthorize("@ss.hasPermi('system:dict:query')")
@GetMapping(value = "/{dictId}") @GetMapping(value = "/{dictId}")
public AjaxResult getInfo(@PathVariable Long dictId) public AjaxResult getInfo(@PathVariable Long dictId)
{ {
return success(dictTypeService.selectDictTypeById(dictId)); return success(dictTypeService.selectDictTypeById(dictId));
} }
/** /**
* 新增字典类型 * 新增字典类型
*/ */
@PreAuthorize("@ss.hasPermi('system:dict:add')") @PreAuthorize("@ss.hasPermi('system:dict:add')")
@Log(title = "字典类型", businessType = BusinessType.INSERT) @Log(title = "字典类型", businessType = BusinessType.INSERT)
@PostMapping @PostMapping
public AjaxResult add(@Validated @RequestBody SysDictType dict) public AjaxResult add(@Validated @RequestBody SysDictType dict)
{ {
if (!dictTypeService.checkDictTypeUnique(dict)) if (!dictTypeService.checkDictTypeUnique(dict))
{ {
return error("新增字典'" + dict.getDictName() + "'失败,字典类型已存在"); return error("新增字典'" + dict.getDictName() + "'失败,字典类型已存在");
} }
dict.setCreateBy(getUsername()); dict.setCreateBy(getUsername());
return toAjax(dictTypeService.insertDictType(dict)); return toAjax(dictTypeService.insertDictType(dict));
} }
/** /**
* 修改字典类型 * 修改字典类型
*/ */
@PreAuthorize("@ss.hasPermi('system:dict:edit')") @PreAuthorize("@ss.hasPermi('system:dict:edit')")
@Log(title = "字典类型", businessType = BusinessType.UPDATE) @Log(title = "字典类型", businessType = BusinessType.UPDATE)
@PutMapping @PutMapping
public AjaxResult edit(@Validated @RequestBody SysDictType dict) public AjaxResult edit(@Validated @RequestBody SysDictType dict)
{ {
if (!dictTypeService.checkDictTypeUnique(dict)) if (!dictTypeService.checkDictTypeUnique(dict))
{ {
return error("修改字典'" + dict.getDictName() + "'失败,字典类型已存在"); return error("修改字典'" + dict.getDictName() + "'失败,字典类型已存在");
} }
dict.setUpdateBy(getUsername()); dict.setUpdateBy(getUsername());
return toAjax(dictTypeService.updateDictType(dict)); return toAjax(dictTypeService.updateDictType(dict));
} }
/** /**
* 删除字典类型 * 删除字典类型
*/ */
@PreAuthorize("@ss.hasPermi('system:dict:remove')") @PreAuthorize("@ss.hasPermi('system:dict:remove')")
@Log(title = "字典类型", businessType = BusinessType.DELETE) @Log(title = "字典类型", businessType = BusinessType.DELETE)
@DeleteMapping("/{dictIds}") @DeleteMapping("/{dictIds}")
public AjaxResult remove(@PathVariable Long[] dictIds) public AjaxResult remove(@PathVariable Long[] dictIds)
{ {
dictTypeService.deleteDictTypeByIds(dictIds); dictTypeService.deleteDictTypeByIds(dictIds);
return success(); return success();
} }
/** /**
* 刷新字典缓存 * 刷新字典缓存
*/ */
@PreAuthorize("@ss.hasPermi('system:dict:remove')") @PreAuthorize("@ss.hasPermi('system:dict:remove')")
@Log(title = "字典类型", businessType = BusinessType.CLEAN) @Log(title = "字典类型", businessType = BusinessType.CLEAN)
@DeleteMapping("/refreshCache") @DeleteMapping("/refreshCache")
public AjaxResult refreshCache() public AjaxResult refreshCache()
{ {
dictTypeService.resetDictCache(); dictTypeService.resetDictCache();
return success(); return success();
} }
/** /**
* 获取字典选择框列表 * 获取字典选择框列表
*/ */
@GetMapping("/optionselect") @GetMapping("/optionselect")
public AjaxResult optionselect() public AjaxResult optionselect()
{ {
List<SysDictType> dictTypes = dictTypeService.selectDictTypeAll(); List<SysDictType> dictTypes = dictTypeService.selectDictTypeAll();
return success(dictTypes); return success(dictTypes);
} }
} }

View File

@@ -1,29 +1,64 @@
package com.ruoyi.web.controller.system; package com.ruoyi.web.controller.system;
import org.springframework.beans.factory.annotation.Autowired; import java.util.Map;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.PostMapping;
import com.ruoyi.common.config.RuoYiConfig; import org.springframework.web.bind.annotation.RequestBody;
import com.ruoyi.common.utils.StringUtils; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/** import com.ruoyi.common.config.RuoYiConfig;
* 首页 import com.ruoyi.common.core.domain.AjaxResult;
* import com.ruoyi.common.core.domain.entity.SysUser;
* @author ruoyi import com.ruoyi.common.utils.SecurityUtils;
*/ import com.ruoyi.common.utils.StringUtils;
@RestController import com.ruoyi.system.service.ISysUserService;
public class SysIndexController
{ /**
/** 系统基础配置 */ * 首页
@Autowired *
private RuoYiConfig ruoyiConfig; * @author ruoyi
*/
/** @RestController
* 访问首页,提示语 public class SysIndexController
*/ {
@RequestMapping("/") /** 系统基础配置 */
public String index() @Autowired
{ private RuoYiConfig ruoyiConfig;
return StringUtils.format("欢迎使用{}后台管理框架当前版本v{},请通过前端地址访问。", ruoyiConfig.getName(), ruoyiConfig.getVersion());
} @Autowired
} private ISysUserService userService;
/**
* 访问首页,提示语
*/
@RequestMapping("/")
public String index()
{
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("解锁成功");
}
}

View File

@@ -1,152 +1,131 @@
package com.ruoyi.web.controller.system; package com.ruoyi.web.controller.system;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.constant.Constants; import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysMenu; import com.ruoyi.common.core.domain.entity.SysMenu;
import com.ruoyi.common.core.domain.entity.SysUser; import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginBody; import com.ruoyi.common.core.domain.model.LoginBody;
import com.ruoyi.common.core.domain.model.LoginUser; import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.text.Convert; 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; import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.system.service.ISysConfigService; import com.ruoyi.system.service.ISysMenuService;
import com.ruoyi.system.service.ISysMenuService;
/**
/** * 登录验证
* 登录验证 *
* * @author ruoyi
* @author ruoyi */
*/ @RestController
@RestController public class SysLoginController
public class SysLoginController {
{ @Autowired
@Autowired private SysLoginService loginService;
private SysLoginService loginService;
@Autowired
@Autowired private ISysMenuService menuService;
private ISysMenuService menuService;
@Autowired
@Autowired private SysPermissionService permissionService;
private SysPermissionService permissionService;
@Autowired
@Autowired private TokenService tokenService;
private TokenService tokenService;
@Autowired
@Autowired private ISysConfigService configService;
private ISysConfigService configService;
/**
@Autowired * 登录方法
private PasswordTransferCryptoService passwordTransferCryptoService; *
* @param loginBody 登录信息
/** * @return 结果
* 登录方法 */
* @PostMapping("/login")
* @param loginBody 登录信息 public AjaxResult login(@RequestBody LoginBody loginBody)
* @return 结果 {
*/ AjaxResult ajax = AjaxResult.success();
@PostMapping("/login") // 生成令牌
public AjaxResult login(@RequestBody LoginBody loginBody) String token = loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(),
{ loginBody.getUuid());
AjaxResult ajax = AjaxResult.success(); ajax.put(Constants.TOKEN, token);
loginBody.setPassword(passwordTransferCryptoService.decrypt(loginBody.getPassword())); return ajax;
// 生成令牌 }
String token = loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(),
loginBody.getUuid()); /**
ajax.put(Constants.TOKEN, token); * 获取用户信息
return ajax; *
} * @return 用户信息
*/
/** @GetMapping("getInfo")
* 登录方法 public AjaxResult getInfo()
* 该方法处理用户登录请求,无需验证码 {
* @param loginBody 登录信息,包含用户名和密码 LoginUser loginUser = SecurityUtils.getLoginUser();
* @return 结果 SysUser user = loginUser.getUser();
*/ // 角色集合
@PostMapping("/login/test") Set<String> roles = permissionService.getRolePermission(user);
public AjaxResult loginWithoutCaptcha (@RequestBody LoginBody loginBody) // 权限集合
{ Set<String> permissions = permissionService.getMenuPermission(user);
AjaxResult ajax = AjaxResult.success(); if (!loginUser.getPermissions().equals(permissions))
// 生成令牌 {
String token = loginService.loginWithoutCaptcha(loginBody.getUsername(), loginBody.getPassword()); loginUser.setPermissions(permissions);
ajax.put(Constants.TOKEN, token); tokenService.refreshToken(loginUser);
return ajax; }
} AjaxResult ajax = AjaxResult.success();
ajax.put("user", user);
/** ajax.put("roles", roles);
* 获取用户信息 ajax.put("permissions", permissions);
* ajax.put("isDefaultModifyPwd", initPasswordIsModify(user.getPwdUpdateDate()));
* @return 用户信息 ajax.put("isPasswordExpired", passwordIsExpiration(user.getPwdUpdateDate()));
*/ return ajax;
@GetMapping("getInfo") }
public AjaxResult getInfo()
{ /**
LoginUser loginUser = SecurityUtils.getLoginUser(); * 获取路由信息
SysUser user = loginUser.getUser(); *
// 角色集合 * @return 路由信息
Set<String> roles = permissionService.getRolePermission(user); */
// 权限集合 @GetMapping("getRouters")
Set<String> permissions = permissionService.getMenuPermission(user); public AjaxResult getRouters()
if (!loginUser.getPermissions().equals(permissions)) {
{ Long userId = SecurityUtils.getUserId();
loginUser.setPermissions(permissions); List<SysMenu> menus = menuService.selectMenuTreeByUserId(userId);
tokenService.refreshToken(loginUser); return AjaxResult.success(menuService.buildMenus(menus));
} }
AjaxResult ajax = AjaxResult.success();
ajax.put("user", user); // 检查初始密码是否提醒修改
ajax.put("roles", roles); public boolean initPasswordIsModify(Date pwdUpdateDate)
ajax.put("permissions", permissions); {
ajax.put("isDefaultModifyPwd", initPasswordIsModify(user.getPwdUpdateDate())); Integer initPasswordModify = Convert.toInt(configService.selectConfigByKey("sys.account.initPasswordModify"));
ajax.put("isPasswordExpired", passwordIsExpiration(user.getPwdUpdateDate())); return initPasswordModify != null && initPasswordModify == 1 && pwdUpdateDate == null;
return ajax; }
}
// 检查密码是否过期
/** public boolean passwordIsExpiration(Date pwdUpdateDate)
* 获取路由信息 {
* Integer passwordValidateDays = Convert.toInt(configService.selectConfigByKey("sys.account.passwordValidateDays"));
* @return 路由信息 if (passwordValidateDays != null && passwordValidateDays > 0)
*/ {
@GetMapping("getRouters") if (StringUtils.isNull(pwdUpdateDate))
public AjaxResult getRouters() {
{ // 如果从未修改过初始密码,直接提醒过期
Long userId = SecurityUtils.getUserId(); return true;
List<SysMenu> menus = menuService.selectMenuTreeByUserId(userId); }
return AjaxResult.success(menuService.buildMenus(menus)); Date nowDate = DateUtils.getNowDate();
} return DateUtils.differentDaysByMillisecond(nowDate, pwdUpdateDate) > passwordValidateDays;
}
// 检查初始密码是否提醒修改 return false;
public boolean initPasswordIsModify(Date pwdUpdateDate) }
{ }
Integer initPasswordModify = Convert.toInt(configService.selectConfigByKey("sys.account.initPasswordModify"));
return initPasswordModify != null && initPasswordModify == 1 && pwdUpdateDate == null;
}
// 检查密码是否过期
public boolean passwordIsExpiration(Date pwdUpdateDate)
{
Integer passwordValidateDays = Convert.toInt(configService.selectConfigByKey("sys.account.passwordValidateDays"));
if (passwordValidateDays != null && passwordValidateDays > 0)
{
if (StringUtils.isNull(pwdUpdateDate))
{
// 如果从未修改过初始密码,直接提醒过期
return true;
}
Date nowDate = DateUtils.getNowDate();
return DateUtils.differentDaysByMillisecond(nowDate, pwdUpdateDate) > passwordValidateDays;
}
return false;
}
}

View File

@@ -1,150 +1,165 @@
package com.ruoyi.web.controller.system; package com.ruoyi.web.controller.system;
import java.util.List; import java.util.List;
import org.springframework.beans.factory.annotation.Autowired; import java.util.Map;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated; import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RequestMapping;
import com.ruoyi.common.annotation.Log; import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.constant.UserConstants; import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController; import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.entity.SysMenu; import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.core.domain.entity.SysMenu;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.system.service.ISysMenuService; import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.service.ISysMenuService;
/**
* 菜单信息 /**
* * 菜单信息
* @author ruoyi *
*/ * @author ruoyi
@RestController */
@RequestMapping("/system/menu") @RestController
public class SysMenuController extends BaseController @RequestMapping("/system/menu")
{ public class SysMenuController extends BaseController
@Autowired {
private ISysMenuService menuService; @Autowired
private ISysMenuService menuService;
/**
* 获取菜单列表 /**
*/ * 获取菜单列表
@PreAuthorize("@ss.hasPermi('system:menu:list')") */
@GetMapping("/list") @PreAuthorize("@ss.hasPermi('system:menu:list')")
public AjaxResult list(SysMenu menu) @GetMapping("/list")
{ public AjaxResult list(SysMenu menu)
List<SysMenu> menus = menuService.selectMenuList(menu, getUserId()); {
return success(menus); List<SysMenu> menus = menuService.selectMenuList(menu, getUserId());
} return success(menus);
}
/**
* 根据菜单编号获取详细信息 /**
*/ * 根据菜单编号获取详细信息
@PreAuthorize("@ss.hasPermi('system:menu:query')") */
@GetMapping(value = "/{menuId}") @PreAuthorize("@ss.hasPermi('system:menu:query')")
public AjaxResult getInfo(@PathVariable Long menuId) @GetMapping(value = "/{menuId}")
{ public AjaxResult getInfo(@PathVariable Long menuId)
return success(menuService.selectMenuById(menuId)); {
} return success(menuService.selectMenuById(menuId));
}
/**
* 获取菜单下拉树列表 /**
*/ * 获取菜单下拉树列表
@GetMapping("/treeselect") */
public AjaxResult treeselect(SysMenu menu) @GetMapping("/treeselect")
{ public AjaxResult treeselect(SysMenu menu)
List<SysMenu> menus = menuService.selectMenuList(menu, getUserId()); {
return success(menuService.buildMenuTreeSelect(menus)); List<SysMenu> menus = menuService.selectMenuList(menu, getUserId());
} return success(menuService.buildMenuTreeSelect(menus));
}
/**
* 加载对应角色菜单列表树 /**
*/ * 加载对应角色菜单列表树
@GetMapping(value = "/roleMenuTreeselect/{roleId}") */
public AjaxResult roleMenuTreeselect(@PathVariable("roleId") Long roleId) @GetMapping(value = "/roleMenuTreeselect/{roleId}")
{ public AjaxResult roleMenuTreeselect(@PathVariable("roleId") Long roleId)
List<SysMenu> menus = menuService.selectMenuList(getUserId()); {
AjaxResult ajax = AjaxResult.success(); List<SysMenu> menus = menuService.selectMenuList(getUserId());
ajax.put("checkedKeys", menuService.selectMenuListByRoleId(roleId)); AjaxResult ajax = AjaxResult.success();
ajax.put("menus", menuService.buildMenuTreeSelect(menus)); ajax.put("checkedKeys", menuService.selectMenuListByRoleId(roleId));
return ajax; ajax.put("menus", menuService.buildMenuTreeSelect(menus));
} return ajax;
}
/**
* 新增菜单 /**
*/ * 新增菜单
@PreAuthorize("@ss.hasPermi('system:menu:add')") */
@Log(title = "菜单管理", businessType = BusinessType.INSERT) @PreAuthorize("@ss.hasPermi('system:menu:add')")
@PostMapping @Log(title = "菜单管理", businessType = BusinessType.INSERT)
public AjaxResult add(@Validated @RequestBody SysMenu menu) @PostMapping
{ public AjaxResult add(@Validated @RequestBody SysMenu menu)
if (!menuService.checkMenuNameUnique(menu)) {
{ if (!menuService.checkMenuNameUnique(menu))
return error("新增菜单'" + menu.getMenuName() + "'失败,菜单名称已存在"); {
} return error("新增菜单'" + menu.getMenuName() + "'失败,菜单名称已存在");
else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) && !StringUtils.ishttp(menu.getPath())) }
{ else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) && !StringUtils.ishttp(menu.getPath()))
return error("新增菜单'" + menu.getMenuName() + "'失败地址必须以http(s)://开头"); {
} return error("新增菜单'" + menu.getMenuName() + "'失败地址必须以http(s)://开头");
else if (!menuService.checkRouteConfigUnique(menu)) }
{ else if (!menuService.checkRouteConfigUnique(menu))
return error("新增菜单'" + menu.getMenuName() + "'失败,路由名称或地址已存在"); {
} return error("新增菜单'" + menu.getMenuName() + "'失败,路由名称或地址已存在");
menu.setCreateBy(getUsername()); }
return toAjax(menuService.insertMenu(menu)); menu.setCreateBy(getUsername());
} return toAjax(menuService.insertMenu(menu));
}
/**
* 修改菜单 /**
*/ * 修改菜单
@PreAuthorize("@ss.hasPermi('system:menu:edit')") */
@Log(title = "菜单管理", businessType = BusinessType.UPDATE) @PreAuthorize("@ss.hasPermi('system:menu:edit')")
@PutMapping @Log(title = "菜单管理", businessType = BusinessType.UPDATE)
public AjaxResult edit(@Validated @RequestBody SysMenu menu) @PutMapping
{ public AjaxResult edit(@Validated @RequestBody SysMenu menu)
if (!menuService.checkMenuNameUnique(menu)) {
{ if (!menuService.checkMenuNameUnique(menu))
return error("修改菜单'" + menu.getMenuName() + "'失败,菜单名称已存在"); {
} return error("修改菜单'" + menu.getMenuName() + "'失败,菜单名称已存在");
else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) && !StringUtils.ishttp(menu.getPath())) }
{ else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) && !StringUtils.ishttp(menu.getPath()))
return error("修改菜单'" + menu.getMenuName() + "'失败地址必须以http(s)://开头"); {
} return error("修改菜单'" + menu.getMenuName() + "'失败地址必须以http(s)://开头");
else if (menu.getMenuId().equals(menu.getParentId())) }
{ else if (menu.getMenuId().equals(menu.getParentId()))
return error("修改菜单'" + menu.getMenuName() + "'失败,上级菜单不能选择自己"); {
} return error("修改菜单'" + menu.getMenuName() + "'失败,上级菜单不能选择自己");
else if (!menuService.checkRouteConfigUnique(menu)) }
{ else if (!menuService.checkRouteConfigUnique(menu))
return error("修改菜单'" + menu.getMenuName() + "'失败,路由名称或地址已存在"); {
} return error("修改菜单'" + menu.getMenuName() + "'失败,路由名称或地址已存在");
menu.setUpdateBy(getUsername()); }
return toAjax(menuService.updateMenu(menu)); menu.setUpdateBy(getUsername());
} return toAjax(menuService.updateMenu(menu));
}
/**
* 删除菜单 /**
*/ * 保存菜单排序
@PreAuthorize("@ss.hasPermi('system:menu:remove')") */
@Log(title = "菜单管理", businessType = BusinessType.DELETE) @PreAuthorize("@ss.hasPermi('system:menu:edit')")
@DeleteMapping("/{menuId}") @Log(title = "保存菜单排序", businessType = BusinessType.UPDATE)
public AjaxResult remove(@PathVariable("menuId") Long menuId) @PutMapping("/updateSort")
{ public AjaxResult updateSort(@RequestBody Map<String, String> params)
if (menuService.hasChildByMenuId(menuId)) {
{ String[] menuIds = params.get("menuIds").split(",");
return warn("存在子菜单,不允许删除"); String[] orderNums = params.get("orderNums").split(",");
} menuService.updateMenuSort(menuIds, orderNums);
if (menuService.checkMenuExistRole(menuId)) return success();
{ }
return warn("菜单已分配,不允许删除");
} /**
return toAjax(menuService.deleteMenuById(menuId)); * 删除菜单
} */
@PreAuthorize("@ss.hasPermi('system:menu:remove')")
@Log(title = "菜单管理", businessType = BusinessType.DELETE)
@DeleteMapping("/{menuId}")
public AjaxResult remove(@PathVariable("menuId") Long menuId)
{
if (menuService.hasChildByMenuId(menuId))
{
return warn("存在子菜单,不允许删除");
}
if (menuService.checkMenuExistRole(menuId))
{
return warn("菜单已分配,不允许删除");
}
return toAjax(menuService.deleteMenuById(menuId));
}
} }

View File

@@ -1,91 +1,138 @@
package com.ruoyi.web.controller.system; package com.ruoyi.web.controller.system;
import java.util.List; import java.util.List;
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;
import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping; 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.RestController; import org.springframework.web.bind.annotation.ResponseBody;
import com.ruoyi.common.annotation.Log; import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.core.controller.BaseController; import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.system.domain.SysNotice; import com.ruoyi.common.core.text.Convert;
import com.ruoyi.system.service.ISysNoticeService; import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.system.domain.SysNotice;
/** import com.ruoyi.system.service.ISysNoticeReadService;
* 公告 信息操作处理 import com.ruoyi.system.service.ISysNoticeService;
*
* @author ruoyi /**
*/ * 公告 信息操作处理
@RestController *
@RequestMapping("/system/notice") * @author ruoyi
public class SysNoticeController extends BaseController */
{ @RestController
@Autowired @RequestMapping("/system/notice")
private ISysNoticeService noticeService; public class SysNoticeController extends BaseController
{
/** @Autowired
* 获取通知公告列表 private ISysNoticeService noticeService;
*/
@PreAuthorize("@ss.hasPermi('system:notice:list')") @Autowired
@GetMapping("/list") private ISysNoticeReadService noticeReadService;
public TableDataInfo list(SysNotice notice)
{ /**
startPage(); * 获取通知公告列表
List<SysNotice> list = noticeService.selectNoticeList(notice); */
return getDataTable(list); @PreAuthorize("@ss.hasPermi('system:notice:list')")
} @GetMapping("/list")
public TableDataInfo list(SysNotice notice)
/** {
* 根据通知公告编号获取详细信息 startPage();
*/ List<SysNotice> list = noticeService.selectNoticeList(notice);
@PreAuthorize("@ss.hasPermi('system:notice:query')") return getDataTable(list);
@GetMapping(value = "/{noticeId}") }
public AjaxResult getInfo(@PathVariable Long noticeId)
{ /**
return success(noticeService.selectNoticeById(noticeId)); * 根据通知公告编号获取详细信息
} */
@PreAuthorize("@ss.hasPermi('system:notice:query')")
/** @GetMapping(value = "/{noticeId}")
* 新增通知公告 public AjaxResult getInfo(@PathVariable Long noticeId)
*/ {
@PreAuthorize("@ss.hasPermi('system:notice:add')") return success(noticeService.selectNoticeById(noticeId));
@Log(title = "通知公告", businessType = BusinessType.INSERT) }
@PostMapping
public AjaxResult add(@Validated @RequestBody SysNotice notice) /**
{ * 新增通知公告
notice.setCreateBy(getUsername()); */
return toAjax(noticeService.insertNotice(notice)); @PreAuthorize("@ss.hasPermi('system:notice:add')")
} @Log(title = "通知公告", businessType = BusinessType.INSERT)
@PostMapping
/** public AjaxResult add(@Validated @RequestBody SysNotice notice)
* 修改通知公告 {
*/ notice.setCreateBy(getUsername());
@PreAuthorize("@ss.hasPermi('system:notice:edit')") return toAjax(noticeService.insertNotice(notice));
@Log(title = "通知公告", businessType = BusinessType.UPDATE) }
@PutMapping
public AjaxResult edit(@Validated @RequestBody SysNotice notice) /**
{ * 修改通知公告
notice.setUpdateBy(getUsername()); */
return toAjax(noticeService.updateNotice(notice)); @PreAuthorize("@ss.hasPermi('system:notice:edit')")
} @Log(title = "通知公告", businessType = BusinessType.UPDATE)
@PutMapping
/** public AjaxResult edit(@Validated @RequestBody SysNotice notice)
* 删除通知公告 {
*/ notice.setUpdateBy(getUsername());
@PreAuthorize("@ss.hasPermi('system:notice:remove')") return toAjax(noticeService.updateNotice(notice));
@Log(title = "通知公告", businessType = BusinessType.DELETE) }
@DeleteMapping("/{noticeIds}")
public AjaxResult remove(@PathVariable Long[] noticeIds) /**
{ * 首页顶部公告列表返回全部正常公告带当前用户已读标记最多5条
return toAjax(noticeService.deleteNoticeByIds(noticeIds)); */
} @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();
}
/**
* 删除通知公告
*/
@PreAuthorize("@ss.hasPermi('system:notice:remove')")
@Log(title = "通知公告", businessType = BusinessType.DELETE)
@DeleteMapping("/{noticeIds}")
public AjaxResult remove(@PathVariable Long[] noticeIds)
{
noticeReadService.deleteByNoticeIds(noticeIds);
return toAjax(noticeService.deleteNoticeByIds(noticeIds));
}
}

View File

@@ -1,129 +1,129 @@
package com.ruoyi.web.controller.system; package com.ruoyi.web.controller.system;
import java.util.List; import java.util.List;
import jakarta.servlet.http.HttpServletResponse; import javax.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;
import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping; 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.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.enums.BusinessType; import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.system.domain.SysPost; import com.ruoyi.system.domain.SysPost;
import com.ruoyi.system.service.ISysPostService; import com.ruoyi.system.service.ISysPostService;
/** /**
* 岗位信息操作处理 * 岗位信息操作处理
* *
* @author ruoyi * @author ruoyi
*/ */
@RestController @RestController
@RequestMapping("/system/post") @RequestMapping("/system/post")
public class SysPostController extends BaseController public class SysPostController extends BaseController
{ {
@Autowired @Autowired
private ISysPostService postService; private ISysPostService postService;
/** /**
* 获取岗位列表 * 获取岗位列表
*/ */
@PreAuthorize("@ss.hasPermi('system:post:list')") @PreAuthorize("@ss.hasPermi('system:post:list')")
@GetMapping("/list") @GetMapping("/list")
public TableDataInfo list(SysPost post) public TableDataInfo list(SysPost post)
{ {
startPage(); startPage();
List<SysPost> list = postService.selectPostList(post); List<SysPost> list = postService.selectPostList(post);
return getDataTable(list); return getDataTable(list);
} }
@Log(title = "岗位管理", businessType = BusinessType.EXPORT) @Log(title = "岗位管理", businessType = BusinessType.EXPORT)
@PreAuthorize("@ss.hasPermi('system:post:export')") @PreAuthorize("@ss.hasPermi('system:post:export')")
@PostMapping("/export") @PostMapping("/export")
public void export(HttpServletResponse response, SysPost post) public void export(HttpServletResponse response, SysPost post)
{ {
List<SysPost> list = postService.selectPostList(post); List<SysPost> list = postService.selectPostList(post);
ExcelUtil<SysPost> util = new ExcelUtil<SysPost>(SysPost.class); ExcelUtil<SysPost> util = new ExcelUtil<SysPost>(SysPost.class);
util.exportExcel(response, list, "岗位数据"); util.exportExcel(response, list, "岗位数据");
} }
/** /**
* 根据岗位编号获取详细信息 * 根据岗位编号获取详细信息
*/ */
@PreAuthorize("@ss.hasPermi('system:post:query')") @PreAuthorize("@ss.hasPermi('system:post:query')")
@GetMapping(value = "/{postId}") @GetMapping(value = "/{postId}")
public AjaxResult getInfo(@PathVariable Long postId) public AjaxResult getInfo(@PathVariable Long postId)
{ {
return success(postService.selectPostById(postId)); return success(postService.selectPostById(postId));
} }
/** /**
* 新增岗位 * 新增岗位
*/ */
@PreAuthorize("@ss.hasPermi('system:post:add')") @PreAuthorize("@ss.hasPermi('system:post:add')")
@Log(title = "岗位管理", businessType = BusinessType.INSERT) @Log(title = "岗位管理", businessType = BusinessType.INSERT)
@PostMapping @PostMapping
public AjaxResult add(@Validated @RequestBody SysPost post) public AjaxResult add(@Validated @RequestBody SysPost post)
{ {
if (!postService.checkPostNameUnique(post)) if (!postService.checkPostNameUnique(post))
{ {
return error("新增岗位'" + post.getPostName() + "'失败,岗位名称已存在"); return error("新增岗位'" + post.getPostName() + "'失败,岗位名称已存在");
} }
else if (!postService.checkPostCodeUnique(post)) else if (!postService.checkPostCodeUnique(post))
{ {
return error("新增岗位'" + post.getPostName() + "'失败,岗位编码已存在"); return error("新增岗位'" + post.getPostName() + "'失败,岗位编码已存在");
} }
post.setCreateBy(getUsername()); post.setCreateBy(getUsername());
return toAjax(postService.insertPost(post)); return toAjax(postService.insertPost(post));
} }
/** /**
* 修改岗位 * 修改岗位
*/ */
@PreAuthorize("@ss.hasPermi('system:post:edit')") @PreAuthorize("@ss.hasPermi('system:post:edit')")
@Log(title = "岗位管理", businessType = BusinessType.UPDATE) @Log(title = "岗位管理", businessType = BusinessType.UPDATE)
@PutMapping @PutMapping
public AjaxResult edit(@Validated @RequestBody SysPost post) public AjaxResult edit(@Validated @RequestBody SysPost post)
{ {
if (!postService.checkPostNameUnique(post)) if (!postService.checkPostNameUnique(post))
{ {
return error("修改岗位'" + post.getPostName() + "'失败,岗位名称已存在"); return error("修改岗位'" + post.getPostName() + "'失败,岗位名称已存在");
} }
else if (!postService.checkPostCodeUnique(post)) else if (!postService.checkPostCodeUnique(post))
{ {
return error("修改岗位'" + post.getPostName() + "'失败,岗位编码已存在"); return error("修改岗位'" + post.getPostName() + "'失败,岗位编码已存在");
} }
post.setUpdateBy(getUsername()); post.setUpdateBy(getUsername());
return toAjax(postService.updatePost(post)); return toAjax(postService.updatePost(post));
} }
/** /**
* 删除岗位 * 删除岗位
*/ */
@PreAuthorize("@ss.hasPermi('system:post:remove')") @PreAuthorize("@ss.hasPermi('system:post:remove')")
@Log(title = "岗位管理", businessType = BusinessType.DELETE) @Log(title = "岗位管理", businessType = BusinessType.DELETE)
@DeleteMapping("/{postIds}") @DeleteMapping("/{postIds}")
public AjaxResult remove(@PathVariable Long[] postIds) public AjaxResult remove(@PathVariable Long[] postIds)
{ {
return toAjax(postService.deletePostByIds(postIds)); return toAjax(postService.deletePostByIds(postIds));
} }
/** /**
* 获取岗位选择框列表 * 获取岗位选择框列表
*/ */
@GetMapping("/optionselect") @GetMapping("/optionselect")
public AjaxResult optionselect() public AjaxResult optionselect()
{ {
List<SysPost> posts = postService.selectPostAll(); List<SysPost> posts = postService.selectPostAll();
return success(posts); return success(posts);
} }
} }

View File

@@ -1,153 +1,149 @@
package com.ruoyi.web.controller.system; package com.ruoyi.web.controller.system;
import java.util.Map; import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping; 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.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import com.ruoyi.common.annotation.Log; import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.config.RuoYiConfig; import com.ruoyi.common.config.RuoYiConfig;
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.domain.entity.SysUser; import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser; import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.enums.BusinessType;
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.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;
/**
/** * 个人信息 业务处理
* 个人信息 业务处理 *
* * @author ruoyi
* @author ruoyi */
*/ @RestController
@RestController @RequestMapping("/system/user/profile")
@RequestMapping("/system/user/profile") public class SysProfileController extends BaseController
public class SysProfileController extends BaseController {
{ @Autowired
@Autowired private ISysUserService userService;
private ISysUserService userService;
@Autowired
@Autowired private TokenService tokenService;
private TokenService tokenService;
/**
@Autowired * 个人信息
private PasswordTransferCryptoService passwordTransferCryptoService; */
@GetMapping
/** public AjaxResult profile()
* 个人信息 {
*/ LoginUser loginUser = getLoginUser();
@GetMapping SysUser user = loginUser.getUser();
public AjaxResult profile() AjaxResult ajax = AjaxResult.success(user);
{ ajax.put("roleGroup", userService.selectUserRoleGroup(loginUser.getUsername()));
LoginUser loginUser = getLoginUser(); ajax.put("postGroup", userService.selectUserPostGroup(loginUser.getUsername()));
SysUser user = loginUser.getUser(); return ajax;
AjaxResult ajax = AjaxResult.success(user); }
ajax.put("roleGroup", userService.selectUserRoleGroup(loginUser.getUsername()));
ajax.put("postGroup", userService.selectUserPostGroup(loginUser.getUsername())); /**
return ajax; * 修改用户
} */
@Log(title = "个人信息", businessType = BusinessType.UPDATE)
/** @PutMapping
* 修改用户 public AjaxResult updateProfile(@RequestBody SysUser user)
*/ {
@Log(title = "个人信息", businessType = BusinessType.UPDATE) LoginUser loginUser = getLoginUser();
@PutMapping SysUser currentUser = loginUser.getUser();
public AjaxResult updateProfile(@RequestBody SysUser user) currentUser.setNickName(user.getNickName());
{ currentUser.setEmail(user.getEmail());
LoginUser loginUser = getLoginUser(); currentUser.setPhonenumber(user.getPhonenumber());
SysUser currentUser = loginUser.getUser(); currentUser.setSex(user.getSex());
currentUser.setNickName(user.getNickName()); if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(currentUser))
currentUser.setEmail(user.getEmail()); {
currentUser.setPhonenumber(user.getPhonenumber()); return error("修改用户'" + loginUser.getUsername() + "'失败,手机号码已存在");
currentUser.setSex(user.getSex()); }
if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(currentUser)) if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(currentUser))
{ {
return error("修改用户'" + loginUser.getUsername() + "'失败,手机号码已存在"); return error("修改用户'" + loginUser.getUsername() + "'失败,邮箱账号已存在");
} }
if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(currentUser)) if (userService.updateUserProfile(currentUser) > 0)
{ {
return error("修改用户'" + loginUser.getUsername() + "'失败,邮箱账号已存在"); // 更新缓存用户信息
} tokenService.setLoginUser(loginUser);
if (userService.updateUserProfile(currentUser) > 0) return success();
{ }
// 更新缓存用户信息 return error("修改个人信息异常,请联系管理员");
tokenService.setLoginUser(loginUser); }
return success();
} /**
return error("修改个人信息异常,请联系管理员"); * 重置密码
} */
@Log(title = "个人信息", businessType = BusinessType.UPDATE)
/** @PutMapping("/updatePwd")
* 重置密码 public AjaxResult updatePwd(@RequestBody Map<String, String> params)
*/ {
@Log(title = "个人信息", businessType = BusinessType.UPDATE) String oldPassword = params.get("oldPassword");
@PutMapping("/updatePwd") String newPassword = params.get("newPassword");
public AjaxResult updatePwd(@RequestBody Map<String, String> params) LoginUser loginUser = getLoginUser();
{ Long userId = loginUser.getUserId();
String oldPassword = passwordTransferCryptoService.decrypt(params.get("oldPassword")); SysUser user = userService.selectUserById(userId);
String newPassword = passwordTransferCryptoService.decrypt(params.get("newPassword")); String password = user.getPassword();
LoginUser loginUser = getLoginUser(); if (!SecurityUtils.matchesPassword(oldPassword, password))
Long userId = loginUser.getUserId(); {
SysUser user = userService.selectUserById(userId); return error("修改密码失败,旧密码错误");
String password = user.getPassword(); }
if (!SecurityUtils.matchesPassword(oldPassword, password)) if (SecurityUtils.matchesPassword(newPassword, password))
{ {
return error("修改密码失败,旧密码错误"); return error("新密码不能与旧密码相同");
} }
if (SecurityUtils.matchesPassword(newPassword, password)) newPassword = SecurityUtils.encryptPassword(newPassword);
{ if (userService.resetUserPwd(userId, newPassword) > 0)
return error("新密码不能与旧密码相同"); {
} // 更新缓存用户密码&密码最后更新时间
newPassword = SecurityUtils.encryptPassword(newPassword); loginUser.getUser().setPwdUpdateDate(DateUtils.getNowDate());
if (userService.resetUserPwd(userId, newPassword) > 0) loginUser.getUser().setPassword(newPassword);
{ tokenService.setLoginUser(loginUser);
// 更新缓存用户密码&密码最后更新时间 return success();
loginUser.getUser().setPwdUpdateDate(DateUtils.getNowDate()); }
loginUser.getUser().setPassword(newPassword); return error("修改密码异常,请联系管理员");
tokenService.setLoginUser(loginUser); }
return success();
} /**
return error("修改密码异常,请联系管理员"); * 头像上传
} */
@Log(title = "用户头像", businessType = BusinessType.UPDATE)
/** @PostMapping("/avatar")
* 头像上传 public AjaxResult avatar(@RequestParam("avatarfile") MultipartFile file) throws Exception
*/ {
@Log(title = "用户头像", businessType = BusinessType.UPDATE) if (!file.isEmpty())
@PostMapping("/avatar") {
public AjaxResult avatar(@RequestParam("avatarfile") MultipartFile file) throws Exception LoginUser loginUser = getLoginUser();
{ String avatar = FileUploadUtils.upload(RuoYiConfig.getAvatarPath(), file, MimeTypeUtils.IMAGE_EXTENSION, true);
if (!file.isEmpty()) if (userService.updateUserAvatar(loginUser.getUserId(), avatar))
{ {
LoginUser loginUser = getLoginUser(); String oldAvatar = loginUser.getUser().getAvatar();
String avatar = FileUploadUtils.upload(RuoYiConfig.getAvatarPath(), file, MimeTypeUtils.IMAGE_EXTENSION, true); if (StringUtils.isNotEmpty(oldAvatar))
if (userService.updateUserAvatar(loginUser.getUserId(), avatar)) {
{ FileUtils.deleteFile(RuoYiConfig.getProfile() + FileUtils.stripPrefix(oldAvatar));
String oldAvatar = loginUser.getUser().getAvatar(); }
if (StringUtils.isNotEmpty(oldAvatar)) AjaxResult ajax = AjaxResult.success();
{ ajax.put("imgUrl", avatar);
FileUtils.deleteFile(RuoYiConfig.getProfile() + FileUtils.stripPrefix(oldAvatar)); // 更新缓存用户头像
} loginUser.getUser().setAvatar(avatar);
AjaxResult ajax = AjaxResult.success(); tokenService.setLoginUser(loginUser);
ajax.put("imgUrl", avatar); return ajax;
// 更新缓存用户头像 }
loginUser.getUser().setAvatar(avatar); }
tokenService.setLoginUser(loginUser); return error("上传图片异常,请联系管理员");
return ajax; }
} }
}
return error("上传图片异常,请联系管理员");
}
}

View File

@@ -1,43 +1,38 @@
package com.ruoyi.web.controller.system; package com.ruoyi.web.controller.system;
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.PostMapping;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController; 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.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;
/**
/** * 注册验证
* 注册验证 *
* * @author ruoyi
* @author ruoyi */
*/ @RestController
@RestController public class SysRegisterController extends BaseController
public class SysRegisterController extends BaseController {
{ @Autowired
@Autowired private SysRegisterService registerService;
private SysRegisterService registerService;
@Autowired
@Autowired private ISysConfigService configService;
private ISysConfigService configService;
@PostMapping("/register")
@Autowired public AjaxResult register(@RequestBody RegisterBody user)
private PasswordTransferCryptoService passwordTransferCryptoService; {
if (!("true".equals(configService.selectConfigByKey("sys.account.registerUser"))))
@PostMapping("/register") {
public AjaxResult register(@RequestBody RegisterBody user) return error("当前系统没有开启注册功能!");
{ }
if (!("true".equals(configService.selectConfigByKey("sys.account.registerUser")))) String msg = registerService.register(user);
{ return StringUtils.isEmpty(msg) ? success() : error(msg);
return error("当前系统没有开启注册功能!"); }
} }
user.setPassword(passwordTransferCryptoService.decrypt(user.getPassword()));
String msg = registerService.register(user);
return StringUtils.isEmpty(msg) ? success() : error(msg);
}
}

View File

@@ -1,262 +1,262 @@
package com.ruoyi.web.controller.system; package com.ruoyi.web.controller.system;
import java.util.List; import java.util.List;
import jakarta.servlet.http.HttpServletResponse; import javax.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;
import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping; 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.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.domain.entity.SysDept; import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysRole; import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser; import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser; import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.enums.BusinessType;
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.SysPermissionService; import com.ruoyi.framework.web.service.SysPermissionService;
import com.ruoyi.framework.web.service.TokenService; import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.domain.SysUserRole; import com.ruoyi.system.domain.SysUserRole;
import com.ruoyi.system.service.ISysDeptService; import com.ruoyi.system.service.ISysDeptService;
import com.ruoyi.system.service.ISysRoleService; import com.ruoyi.system.service.ISysRoleService;
import com.ruoyi.system.service.ISysUserService; import com.ruoyi.system.service.ISysUserService;
/** /**
* 角色信息 * 角色信息
* *
* @author ruoyi * @author ruoyi
*/ */
@RestController @RestController
@RequestMapping("/system/role") @RequestMapping("/system/role")
public class SysRoleController extends BaseController public class SysRoleController extends BaseController
{ {
@Autowired @Autowired
private ISysRoleService roleService; private ISysRoleService roleService;
@Autowired @Autowired
private TokenService tokenService; private TokenService tokenService;
@Autowired @Autowired
private SysPermissionService permissionService; private SysPermissionService permissionService;
@Autowired @Autowired
private ISysUserService userService; private ISysUserService userService;
@Autowired @Autowired
private ISysDeptService deptService; private ISysDeptService deptService;
@PreAuthorize("@ss.hasPermi('system:role:list')") @PreAuthorize("@ss.hasPermi('system:role:list')")
@GetMapping("/list") @GetMapping("/list")
public TableDataInfo list(SysRole role) public TableDataInfo list(SysRole role)
{ {
startPage(); startPage();
List<SysRole> list = roleService.selectRoleList(role); List<SysRole> list = roleService.selectRoleList(role);
return getDataTable(list); return getDataTable(list);
} }
@Log(title = "角色管理", businessType = BusinessType.EXPORT) @Log(title = "角色管理", businessType = BusinessType.EXPORT)
@PreAuthorize("@ss.hasPermi('system:role:export')") @PreAuthorize("@ss.hasPermi('system:role:export')")
@PostMapping("/export") @PostMapping("/export")
public void export(HttpServletResponse response, SysRole role) public void export(HttpServletResponse response, SysRole role)
{ {
List<SysRole> list = roleService.selectRoleList(role); List<SysRole> list = roleService.selectRoleList(role);
ExcelUtil<SysRole> util = new ExcelUtil<SysRole>(SysRole.class); ExcelUtil<SysRole> util = new ExcelUtil<SysRole>(SysRole.class);
util.exportExcel(response, list, "角色数据"); util.exportExcel(response, list, "角色数据");
} }
/** /**
* 根据角色编号获取详细信息 * 根据角色编号获取详细信息
*/ */
@PreAuthorize("@ss.hasPermi('system:role:query')") @PreAuthorize("@ss.hasPermi('system:role:query')")
@GetMapping(value = "/{roleId}") @GetMapping(value = "/{roleId}")
public AjaxResult getInfo(@PathVariable Long roleId) public AjaxResult getInfo(@PathVariable Long roleId)
{ {
roleService.checkRoleDataScope(roleId); roleService.checkRoleDataScope(roleId);
return success(roleService.selectRoleById(roleId)); return success(roleService.selectRoleById(roleId));
} }
/** /**
* 新增角色 * 新增角色
*/ */
@PreAuthorize("@ss.hasPermi('system:role:add')") @PreAuthorize("@ss.hasPermi('system:role:add')")
@Log(title = "角色管理", businessType = BusinessType.INSERT) @Log(title = "角色管理", businessType = BusinessType.INSERT)
@PostMapping @PostMapping
public AjaxResult add(@Validated @RequestBody SysRole role) public AjaxResult add(@Validated @RequestBody SysRole role)
{ {
if (!roleService.checkRoleNameUnique(role)) if (!roleService.checkRoleNameUnique(role))
{ {
return error("新增角色'" + role.getRoleName() + "'失败,角色名称已存在"); return error("新增角色'" + role.getRoleName() + "'失败,角色名称已存在");
} }
else if (!roleService.checkRoleKeyUnique(role)) else if (!roleService.checkRoleKeyUnique(role))
{ {
return error("新增角色'" + role.getRoleName() + "'失败,角色权限已存在"); return error("新增角色'" + role.getRoleName() + "'失败,角色权限已存在");
} }
role.setCreateBy(getUsername()); role.setCreateBy(getUsername());
return toAjax(roleService.insertRole(role)); return toAjax(roleService.insertRole(role));
} }
/** /**
* 修改保存角色 * 修改保存角色
*/ */
@PreAuthorize("@ss.hasPermi('system:role:edit')") @PreAuthorize("@ss.hasPermi('system:role:edit')")
@Log(title = "角色管理", businessType = BusinessType.UPDATE) @Log(title = "角色管理", businessType = BusinessType.UPDATE)
@PutMapping @PutMapping
public AjaxResult edit(@Validated @RequestBody SysRole role) public AjaxResult edit(@Validated @RequestBody SysRole role)
{ {
roleService.checkRoleAllowed(role); roleService.checkRoleAllowed(role);
roleService.checkRoleDataScope(role.getRoleId()); roleService.checkRoleDataScope(role.getRoleId());
if (!roleService.checkRoleNameUnique(role)) if (!roleService.checkRoleNameUnique(role))
{ {
return error("修改角色'" + role.getRoleName() + "'失败,角色名称已存在"); return error("修改角色'" + role.getRoleName() + "'失败,角色名称已存在");
} }
else if (!roleService.checkRoleKeyUnique(role)) else if (!roleService.checkRoleKeyUnique(role))
{ {
return error("修改角色'" + role.getRoleName() + "'失败,角色权限已存在"); return error("修改角色'" + role.getRoleName() + "'失败,角色权限已存在");
} }
role.setUpdateBy(getUsername()); role.setUpdateBy(getUsername());
if (roleService.updateRole(role) > 0) if (roleService.updateRole(role) > 0)
{ {
// 更新缓存用户权限 // 更新缓存用户权限
LoginUser loginUser = getLoginUser(); LoginUser loginUser = getLoginUser();
if (StringUtils.isNotNull(loginUser.getUser()) && !loginUser.getUser().isAdmin()) if (StringUtils.isNotNull(loginUser.getUser()) && !loginUser.getUser().isAdmin())
{ {
loginUser.setUser(userService.selectUserByUserName(loginUser.getUser().getUserName())); loginUser.setUser(userService.selectUserByUserName(loginUser.getUser().getUserName()));
loginUser.setPermissions(permissionService.getMenuPermission(loginUser.getUser())); loginUser.setPermissions(permissionService.getMenuPermission(loginUser.getUser()));
tokenService.setLoginUser(loginUser); tokenService.setLoginUser(loginUser);
} }
return success(); return success();
} }
return error("修改角色'" + role.getRoleName() + "'失败,请联系管理员"); return error("修改角色'" + role.getRoleName() + "'失败,请联系管理员");
} }
/** /**
* 修改保存数据权限 * 修改保存数据权限
*/ */
@PreAuthorize("@ss.hasPermi('system:role:edit')") @PreAuthorize("@ss.hasPermi('system:role:edit')")
@Log(title = "角色管理", businessType = BusinessType.UPDATE) @Log(title = "角色管理", businessType = BusinessType.UPDATE)
@PutMapping("/dataScope") @PutMapping("/dataScope")
public AjaxResult dataScope(@RequestBody SysRole role) public AjaxResult dataScope(@RequestBody SysRole role)
{ {
roleService.checkRoleAllowed(role); roleService.checkRoleAllowed(role);
roleService.checkRoleDataScope(role.getRoleId()); roleService.checkRoleDataScope(role.getRoleId());
return toAjax(roleService.authDataScope(role)); return toAjax(roleService.authDataScope(role));
} }
/** /**
* 状态修改 * 状态修改
*/ */
@PreAuthorize("@ss.hasPermi('system:role:edit')") @PreAuthorize("@ss.hasPermi('system:role:edit')")
@Log(title = "角色管理", businessType = BusinessType.UPDATE) @Log(title = "角色管理", businessType = BusinessType.UPDATE)
@PutMapping("/changeStatus") @PutMapping("/changeStatus")
public AjaxResult changeStatus(@RequestBody SysRole role) public AjaxResult changeStatus(@RequestBody SysRole role)
{ {
roleService.checkRoleAllowed(role); roleService.checkRoleAllowed(role);
roleService.checkRoleDataScope(role.getRoleId()); roleService.checkRoleDataScope(role.getRoleId());
role.setUpdateBy(getUsername()); role.setUpdateBy(getUsername());
return toAjax(roleService.updateRoleStatus(role)); return toAjax(roleService.updateRoleStatus(role));
} }
/** /**
* 删除角色 * 删除角色
*/ */
@PreAuthorize("@ss.hasPermi('system:role:remove')") @PreAuthorize("@ss.hasPermi('system:role:remove')")
@Log(title = "角色管理", businessType = BusinessType.DELETE) @Log(title = "角色管理", businessType = BusinessType.DELETE)
@DeleteMapping("/{roleIds}") @DeleteMapping("/{roleIds}")
public AjaxResult remove(@PathVariable Long[] roleIds) public AjaxResult remove(@PathVariable Long[] roleIds)
{ {
return toAjax(roleService.deleteRoleByIds(roleIds)); return toAjax(roleService.deleteRoleByIds(roleIds));
} }
/** /**
* 获取角色选择框列表 * 获取角色选择框列表
*/ */
@PreAuthorize("@ss.hasPermi('system:role:query')") @PreAuthorize("@ss.hasPermi('system:role:query')")
@GetMapping("/optionselect") @GetMapping("/optionselect")
public AjaxResult optionselect() public AjaxResult optionselect()
{ {
return success(roleService.selectRoleAll()); return success(roleService.selectRoleAll());
} }
/** /**
* 查询已分配用户角色列表 * 查询已分配用户角色列表
*/ */
@PreAuthorize("@ss.hasPermi('system:role:list')") @PreAuthorize("@ss.hasPermi('system:role:list')")
@GetMapping("/authUser/allocatedList") @GetMapping("/authUser/allocatedList")
public TableDataInfo allocatedList(SysUser user) public TableDataInfo allocatedList(SysUser user)
{ {
startPage(); startPage();
List<SysUser> list = userService.selectAllocatedList(user); List<SysUser> list = userService.selectAllocatedList(user);
return getDataTable(list); return getDataTable(list);
} }
/** /**
* 查询未分配用户角色列表 * 查询未分配用户角色列表
*/ */
@PreAuthorize("@ss.hasPermi('system:role:list')") @PreAuthorize("@ss.hasPermi('system:role:list')")
@GetMapping("/authUser/unallocatedList") @GetMapping("/authUser/unallocatedList")
public TableDataInfo unallocatedList(SysUser user) public TableDataInfo unallocatedList(SysUser user)
{ {
startPage(); startPage();
List<SysUser> list = userService.selectUnallocatedList(user); List<SysUser> list = userService.selectUnallocatedList(user);
return getDataTable(list); return getDataTable(list);
} }
/** /**
* 取消授权用户 * 取消授权用户
*/ */
@PreAuthorize("@ss.hasPermi('system:role:edit')") @PreAuthorize("@ss.hasPermi('system:role:edit')")
@Log(title = "角色管理", businessType = BusinessType.GRANT) @Log(title = "角色管理", businessType = BusinessType.GRANT)
@PutMapping("/authUser/cancel") @PutMapping("/authUser/cancel")
public AjaxResult cancelAuthUser(@RequestBody SysUserRole userRole) public AjaxResult cancelAuthUser(@RequestBody SysUserRole userRole)
{ {
return toAjax(roleService.deleteAuthUser(userRole)); return toAjax(roleService.deleteAuthUser(userRole));
} }
/** /**
* 批量取消授权用户 * 批量取消授权用户
*/ */
@PreAuthorize("@ss.hasPermi('system:role:edit')") @PreAuthorize("@ss.hasPermi('system:role:edit')")
@Log(title = "角色管理", businessType = BusinessType.GRANT) @Log(title = "角色管理", businessType = BusinessType.GRANT)
@PutMapping("/authUser/cancelAll") @PutMapping("/authUser/cancelAll")
public AjaxResult cancelAuthUserAll(Long roleId, Long[] userIds) public AjaxResult cancelAuthUserAll(Long roleId, Long[] userIds)
{ {
return toAjax(roleService.deleteAuthUsers(roleId, userIds)); return toAjax(roleService.deleteAuthUsers(roleId, userIds));
} }
/** /**
* 批量选择用户授权 * 批量选择用户授权
*/ */
@PreAuthorize("@ss.hasPermi('system:role:edit')") @PreAuthorize("@ss.hasPermi('system:role:edit')")
@Log(title = "角色管理", businessType = BusinessType.GRANT) @Log(title = "角色管理", businessType = BusinessType.GRANT)
@PutMapping("/authUser/selectAll") @PutMapping("/authUser/selectAll")
public AjaxResult selectAuthUserAll(Long roleId, Long[] userIds) public AjaxResult selectAuthUserAll(Long roleId, Long[] userIds)
{ {
roleService.checkRoleDataScope(roleId); roleService.checkRoleDataScope(roleId);
return toAjax(roleService.insertAuthUsers(roleId, userIds)); return toAjax(roleService.insertAuthUsers(roleId, userIds));
} }
/** /**
* 获取对应角色部门树列表 * 获取对应角色部门树列表
*/ */
@PreAuthorize("@ss.hasPermi('system:role:query')") @PreAuthorize("@ss.hasPermi('system:role:query')")
@GetMapping(value = "/deptTree/{roleId}") @GetMapping(value = "/deptTree/{roleId}")
public AjaxResult deptTree(@PathVariable("roleId") Long roleId) public AjaxResult deptTree(@PathVariable("roleId") Long roleId)
{ {
AjaxResult ajax = AjaxResult.success(); AjaxResult ajax = AjaxResult.success();
ajax.put("checkedKeys", deptService.selectDeptListByRoleId(roleId)); ajax.put("checkedKeys", deptService.selectDeptListByRoleId(roleId));
ajax.put("depts", deptService.selectDeptTreeList(new SysDept())); ajax.put("depts", deptService.selectDeptTreeList(new SysDept()));
return ajax; return ajax;
} }
} }

View File

@@ -1,262 +1,256 @@
package com.ruoyi.web.controller.system; 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 jakarta.servlet.http.HttpServletResponse; import javax.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;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping; 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.RestController; import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
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.domain.entity.SysDept; import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysRole; import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser; import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType; 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; import com.ruoyi.system.service.ISysUserService;
import com.ruoyi.system.service.ISysUserService;
/**
/** * 用户信息
* 用户信息 *
* * @author ruoyi
* @author ruoyi */
*/ @RestController
@RestController @RequestMapping("/system/user")
@RequestMapping("/system/user") public class SysUserController extends BaseController
public class SysUserController extends BaseController {
{ @Autowired
@Autowired private ISysUserService userService;
private ISysUserService userService;
@Autowired
@Autowired private ISysRoleService roleService;
private ISysRoleService roleService;
@Autowired
@Autowired private ISysDeptService deptService;
private ISysDeptService deptService;
@Autowired
@Autowired private ISysPostService postService;
private ISysPostService postService;
/**
@Autowired * 获取用户列表
private PasswordTransferCryptoService passwordTransferCryptoService; */
@PreAuthorize("@ss.hasPermi('system:user:list')")
/** @GetMapping("/list")
* 获取用户列表 public TableDataInfo list(SysUser user)
*/ {
@PreAuthorize("@ss.hasPermi('system:user:list')") startPage();
@GetMapping("/list") List<SysUser> list = userService.selectUserList(user);
public TableDataInfo list(SysUser user) return getDataTable(list);
{ }
startPage();
List<SysUser> list = userService.selectUserList(user); @Log(title = "用户管理", businessType = BusinessType.EXPORT)
return getDataTable(list); @PreAuthorize("@ss.hasPermi('system:user:export')")
} @PostMapping("/export")
public void export(HttpServletResponse response, SysUser user)
@Log(title = "用户管理", businessType = BusinessType.EXPORT) {
@PreAuthorize("@ss.hasPermi('system:user:export')") List<SysUser> list = userService.selectUserList(user);
@PostMapping("/export") ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
public void export(HttpServletResponse response, SysUser user) util.exportExcel(response, list, "用户数据");
{ }
List<SysUser> list = userService.selectUserList(user);
ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class); @Log(title = "用户管理", businessType = BusinessType.IMPORT)
util.exportExcel(response, list, "用户数据"); @PreAuthorize("@ss.hasPermi('system:user:import')")
} @PostMapping("/importData")
public AjaxResult importData(MultipartFile file, boolean updateSupport) throws Exception
@Log(title = "用户管理", businessType = BusinessType.IMPORT) {
@PreAuthorize("@ss.hasPermi('system:user:import')") ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
@PostMapping("/importData") List<SysUser> userList = util.importExcel(file.getInputStream());
public AjaxResult importData(MultipartFile file, boolean updateSupport) throws Exception String operName = getUsername();
{ String message = userService.importUser(userList, updateSupport, operName);
ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class); return success(message);
List<SysUser> userList = util.importExcel(file.getInputStream()); }
String operName = getUsername();
String message = userService.importUser(userList, updateSupport, operName); @PostMapping("/importTemplate")
return success(message); public void importTemplate(HttpServletResponse response)
} {
ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
@PostMapping("/importTemplate") util.importTemplateExcel(response, "用户数据");
public void importTemplate(HttpServletResponse response) }
{
ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class); /**
util.importTemplateExcel(response, "用户数据"); * 根据用户编号获取详细信息
} */
@PreAuthorize("@ss.hasPermi('system:user:query')")
/** @GetMapping(value = { "/", "/{userId}" })
* 根据用户编号获取详细信息 public AjaxResult getInfo(@PathVariable(value = "userId", required = false) Long userId)
*/ {
@PreAuthorize("@ss.hasPermi('system:user:query')") AjaxResult ajax = AjaxResult.success();
@GetMapping(value = { "/", "/{userId}" }) if (StringUtils.isNotNull(userId))
public AjaxResult getInfo(@PathVariable(value = "userId", required = false) Long userId) {
{ userService.checkUserDataScope(userId);
AjaxResult ajax = AjaxResult.success(); SysUser sysUser = userService.selectUserById(userId);
if (StringUtils.isNotNull(userId)) ajax.put(AjaxResult.DATA_TAG, sysUser);
{ ajax.put("postIds", postService.selectPostListByUserId(userId));
userService.checkUserDataScope(userId); ajax.put("roleIds", sysUser.getRoles().stream().map(SysRole::getRoleId).collect(Collectors.toList()));
SysUser sysUser = userService.selectUserById(userId); }
ajax.put(AjaxResult.DATA_TAG, sysUser); List<SysRole> roles = roleService.selectRoleAll();
ajax.put("postIds", postService.selectPostListByUserId(userId)); ajax.put("roles", SecurityUtils.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
ajax.put("roleIds", sysUser.getRoles().stream().map(SysRole::getRoleId).collect(Collectors.toList())); ajax.put("posts", postService.selectPostAll());
} return ajax;
List<SysRole> roles = roleService.selectRoleAll(); }
ajax.put("roles", SecurityUtils.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
ajax.put("posts", postService.selectPostAll()); /**
return ajax; * 新增用户
} */
@PreAuthorize("@ss.hasPermi('system:user:add')")
/** @Log(title = "用户管理", businessType = BusinessType.INSERT)
* 新增用户 @PostMapping
*/ public AjaxResult add(@Validated @RequestBody SysUser user)
@PreAuthorize("@ss.hasPermi('system:user:add')") {
@Log(title = "用户管理", businessType = BusinessType.INSERT) deptService.checkDeptDataScope(user.getDeptId());
@PostMapping roleService.checkRoleDataScope(user.getRoleIds());
public AjaxResult add(@Validated @RequestBody SysUser user) if (!userService.checkUserNameUnique(user))
{ {
deptService.checkDeptDataScope(user.getDeptId()); return error("新增用户'" + user.getUserName() + "'失败,登录账号已存在");
roleService.checkRoleDataScope(user.getRoleIds()); }
if (!userService.checkUserNameUnique(user)) else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user))
{ {
return error("新增用户'" + user.getUserName() + "'失败,登录账号已存在"); return error("新增用户'" + user.getUserName() + "'失败,手机号码已存在");
} }
else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user)) else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user))
{ {
return error("新增用户'" + user.getUserName() + "'失败,手机号码已存在"); return error("新增用户'" + user.getUserName() + "'失败,邮箱账号已存在");
} }
else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user)) user.setCreateBy(getUsername());
{ user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
return error("新增用户'" + user.getUserName() + "'失败,邮箱账号已存在"); return toAjax(userService.insertUser(user));
} }
user.setCreateBy(getUsername());
user.setPassword(passwordTransferCryptoService.decrypt(user.getPassword())); /**
user.setPassword(SecurityUtils.encryptPassword(user.getPassword())); * 修改用户
return toAjax(userService.insertUser(user)); */
} @PreAuthorize("@ss.hasPermi('system:user:edit')")
@Log(title = "用户管理", businessType = BusinessType.UPDATE)
/** @PutMapping
* 修改用户 public AjaxResult edit(@Validated @RequestBody SysUser user)
*/ {
@PreAuthorize("@ss.hasPermi('system:user:edit')") userService.checkUserAllowed(user);
@Log(title = "用户管理", businessType = BusinessType.UPDATE) userService.checkUserDataScope(user.getUserId());
@PutMapping deptService.checkDeptDataScope(user.getDeptId());
public AjaxResult edit(@Validated @RequestBody SysUser user) roleService.checkRoleDataScope(user.getRoleIds());
{ if (!userService.checkUserNameUnique(user))
userService.checkUserAllowed(user); {
userService.checkUserDataScope(user.getUserId()); return error("修改用户'" + user.getUserName() + "'失败,登录账号已存在");
deptService.checkDeptDataScope(user.getDeptId()); }
roleService.checkRoleDataScope(user.getRoleIds()); else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user))
if (!userService.checkUserNameUnique(user)) {
{ return error("修改用户'" + user.getUserName() + "'失败,手机号码已存在");
return error("修改用户'" + user.getUserName() + "'失败,登录账号已存在"); }
} else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user))
else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user)) {
{ return error("修改用户'" + user.getUserName() + "'失败,邮箱账号已存在");
return error("修改用户'" + user.getUserName() + "'失败,手机号码已存在"); }
} user.setUpdateBy(getUsername());
else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user)) return toAjax(userService.updateUser(user));
{ }
return error("修改用户'" + user.getUserName() + "'失败,邮箱账号已存在");
} /**
user.setUpdateBy(getUsername()); * 删除用户
return toAjax(userService.updateUser(user)); */
} @PreAuthorize("@ss.hasPermi('system:user:remove')")
@Log(title = "用户管理", businessType = BusinessType.DELETE)
/** @DeleteMapping("/{userIds}")
* 删除用户 public AjaxResult remove(@PathVariable Long[] userIds)
*/ {
@PreAuthorize("@ss.hasPermi('system:user:remove')") if (ArrayUtils.contains(userIds, getUserId()))
@Log(title = "用户管理", businessType = BusinessType.DELETE) {
@DeleteMapping("/{userIds}") return error("当前用户不能删除");
public AjaxResult remove(@PathVariable Long[] userIds) }
{ return toAjax(userService.deleteUserByIds(userIds));
if (ArrayUtils.contains(userIds, getUserId())) }
{
return error("当前用户不能删除"); /**
} * 重置密码
return toAjax(userService.deleteUserByIds(userIds)); */
} @PreAuthorize("@ss.hasPermi('system:user:resetPwd')")
@Log(title = "用户管理", businessType = BusinessType.UPDATE)
/** @PutMapping("/resetPwd")
* 重置密码 public AjaxResult resetPwd(@RequestBody SysUser user)
*/ {
@PreAuthorize("@ss.hasPermi('system:user:resetPwd')") userService.checkUserAllowed(user);
@Log(title = "用户管理", businessType = BusinessType.UPDATE) userService.checkUserDataScope(user.getUserId());
@PutMapping("/resetPwd") user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
public AjaxResult resetPwd(@RequestBody SysUser user) user.setUpdateBy(getUsername());
{ return toAjax(userService.resetPwd(user));
userService.checkUserAllowed(user); }
userService.checkUserDataScope(user.getUserId());
user.setPassword(passwordTransferCryptoService.decrypt(user.getPassword())); /**
user.setPassword(SecurityUtils.encryptPassword(user.getPassword())); * 状态修改
user.setUpdateBy(getUsername()); */
return toAjax(userService.resetPwd(user)); @PreAuthorize("@ss.hasPermi('system:user:edit')")
} @Log(title = "用户管理", businessType = BusinessType.UPDATE)
@PutMapping("/changeStatus")
/** public AjaxResult changeStatus(@RequestBody SysUser user)
* 状态修改 {
*/ userService.checkUserAllowed(user);
@PreAuthorize("@ss.hasPermi('system:user:edit')") userService.checkUserDataScope(user.getUserId());
@Log(title = "用户管理", businessType = BusinessType.UPDATE) user.setUpdateBy(getUsername());
@PutMapping("/changeStatus") return toAjax(userService.updateUserStatus(user));
public AjaxResult changeStatus(@RequestBody SysUser user) }
{
userService.checkUserAllowed(user); /**
userService.checkUserDataScope(user.getUserId()); * 根据用户编号获取授权角色
user.setUpdateBy(getUsername()); */
return toAjax(userService.updateUserStatus(user)); @PreAuthorize("@ss.hasPermi('system:user:query')")
} @GetMapping("/authRole/{userId}")
public AjaxResult authRole(@PathVariable("userId") Long userId)
/** {
* 根据用户编号获取授权角色 AjaxResult ajax = AjaxResult.success();
*/ SysUser user = userService.selectUserById(userId);
@PreAuthorize("@ss.hasPermi('system:user:query')") List<SysRole> roles = roleService.selectRolesByUserId(userId);
@GetMapping("/authRole/{userId}") ajax.put("user", user);
public AjaxResult authRole(@PathVariable("userId") Long userId) ajax.put("roles", SecurityUtils.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
{ return ajax;
AjaxResult ajax = AjaxResult.success(); }
SysUser user = userService.selectUserById(userId);
List<SysRole> roles = roleService.selectRolesByUserId(userId); /**
ajax.put("user", user); * 用户授权角色
ajax.put("roles", SecurityUtils.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList())); */
return ajax; @PreAuthorize("@ss.hasPermi('system:user:edit')")
} @Log(title = "用户管理", businessType = BusinessType.GRANT)
@PutMapping("/authRole")
/** public AjaxResult insertAuthRole(Long userId, Long[] roleIds)
* 用户授权角色 {
*/ userService.checkUserDataScope(userId);
@PreAuthorize("@ss.hasPermi('system:user:edit')") roleService.checkRoleDataScope(roleIds);
@Log(title = "用户管理", businessType = BusinessType.GRANT) userService.insertUserAuth(userId, roleIds);
@PutMapping("/authRole") return success();
public AjaxResult insertAuthRole(Long userId, Long[] roleIds) }
{
userService.checkUserDataScope(userId); /**
roleService.checkRoleDataScope(roleIds); * 获取部门树列表
userService.insertUserAuth(userId, roleIds); */
return success(); @PreAuthorize("@ss.hasPermi('system:user:list')")
} @GetMapping("/deptTree")
public AjaxResult deptTree(SysDept dept)
/** {
* 获取部门树列表 return success(deptService.selectDeptTreeList(dept));
*/ }
@PreAuthorize("@ss.hasPermi('system:user:list')") }
@GetMapping("/deptTree")
public AjaxResult deptTree(SysDept dept)
{
return success(deptService.selectDeptTreeList(dept));
}
}

View File

@@ -1,175 +1,183 @@
package com.ruoyi.web.controller.tool; package com.ruoyi.web.controller.tool;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping; 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.RestController; 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.v3.oas.annotations.Operation; import io.swagger.annotations.Api;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.annotations.ApiImplicitParam;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiModel;
/** import io.swagger.annotations.ApiModelProperty;
* swagger 用户测试方法 import io.swagger.annotations.ApiOperation;
*
* @author ruoyi /**
*/ * swagger 用户测试方法
@Tag(name = "用户信息管理") *
@RestController * @author ruoyi
@RequestMapping("/test/user") */
public class TestController extends BaseController @Api("用户信息管理")
{ @RestController
private final static Map<Integer, UserEntity> users = new LinkedHashMap<Integer, UserEntity>(); @RequestMapping("/test/user")
{ public class TestController extends BaseController
users.put(1, new UserEntity(1, "admin", "admin123", "15888888888")); {
users.put(2, new UserEntity(2, "ry", "admin123", "15666666666")); private final static Map<Integer, UserEntity> users = new LinkedHashMap<Integer, UserEntity>();
} {
users.put(1, new UserEntity(1, "admin", "admin123", "15888888888"));
@Operation(summary = "获取用户列表") users.put(2, new UserEntity(2, "ry", "admin123", "15666666666"));
@GetMapping("/list") }
public R<List<UserEntity>> userList()
{ @ApiOperation("获取用户列表")
List<UserEntity> userList = new ArrayList<UserEntity>(users.values()); @GetMapping("/list")
return R.ok(userList); public R<List<UserEntity>> userList()
} {
List<UserEntity> userList = new ArrayList<UserEntity>(users.values());
@Operation(summary = "获取用户详细") return R.ok(userList);
@GetMapping("/{userId}") }
public R<UserEntity> getUser(@PathVariable(name = "userId")
Integer userId) @ApiOperation("获取用户详细")
{ @ApiImplicitParam(name = "userId", value = "用户ID", required = true, dataType = "int", paramType = "path", dataTypeClass = Integer.class)
if (!users.isEmpty() && users.containsKey(userId)) @GetMapping("/{userId}")
{ public R<UserEntity> getUser(@PathVariable Integer userId)
return R.ok(users.get(userId)); {
} if (!users.isEmpty() && users.containsKey(userId))
else {
{ return R.ok(users.get(userId));
return R.fail("用户不存在"); }
} else
} {
return R.fail("用户不存在");
@Operation(summary = "新增用户") }
@PostMapping("/save") }
public R<String> save(UserEntity user)
{ @ApiOperation("新增用户")
if (StringUtils.isNull(user) || StringUtils.isNull(user.getUserId())) @ApiImplicitParams({
{ @ApiImplicitParam(name = "userId", value = "用户id", dataType = "Integer", dataTypeClass = Integer.class),
return R.fail("用户ID不能为空"); @ApiImplicitParam(name = "username", value = "用户名称", dataType = "String", dataTypeClass = String.class),
} @ApiImplicitParam(name = "password", value = "用户密码", dataType = "String", dataTypeClass = String.class),
users.put(user.getUserId(), user); @ApiImplicitParam(name = "mobile", value = "用户手机", dataType = "String", dataTypeClass = String.class)
return R.ok(); })
} @PostMapping("/save")
public R<String> save(UserEntity user)
@Operation(summary = "更新用户") {
@PutMapping("/update") if (StringUtils.isNull(user) || StringUtils.isNull(user.getUserId()))
public R<String> update(@RequestBody {
UserEntity user) return R.fail("用户ID不能为空");
{ }
if (StringUtils.isNull(user) || StringUtils.isNull(user.getUserId())) users.put(user.getUserId(), user);
{ return R.ok();
return R.fail("用户ID不能为空"); }
}
if (users.isEmpty() || !users.containsKey(user.getUserId())) @ApiOperation("更新用户")
{ @PutMapping("/update")
return R.fail("用户不存在"); public R<String> update(@RequestBody UserEntity user)
} {
users.remove(user.getUserId()); if (StringUtils.isNull(user) || StringUtils.isNull(user.getUserId()))
users.put(user.getUserId(), user); {
return R.ok(); return R.fail("用户ID不能为空");
} }
if (users.isEmpty() || !users.containsKey(user.getUserId()))
@Operation(summary = "删除用户信息") {
@DeleteMapping("/{userId}") return R.fail("用户不存在");
public R<String> delete(@PathVariable(name = "userId") }
Integer userId) users.remove(user.getUserId());
{ users.put(user.getUserId(), user);
if (!users.isEmpty() && users.containsKey(userId)) return R.ok();
{ }
users.remove(userId);
return R.ok(); @ApiOperation("删除用户信息")
} @ApiImplicitParam(name = "userId", value = "用户ID", required = true, dataType = "int", paramType = "path", dataTypeClass = Integer.class)
else @DeleteMapping("/{userId}")
{ public R<String> delete(@PathVariable Integer userId)
return R.fail("用户不存在"); {
} if (!users.isEmpty() && users.containsKey(userId))
} {
} users.remove(userId);
return R.ok();
@Schema(description = "用户实体") }
class UserEntity else
{ {
@Schema(title = "用户ID") return R.fail("用户不存在");
private Integer userId; }
}
@Schema(title = "用户名称") }
private String username;
@ApiModel(value = "UserEntity", description = "用户实体")
@Schema(title = "用户密码") class UserEntity
private String password; {
@ApiModelProperty("用户ID")
@Schema(title = "用户手机") private Integer userId;
private String mobile;
@ApiModelProperty("用户名称")
public UserEntity() private String username;
{
@ApiModelProperty("用户密码")
} private String password;
public UserEntity(Integer userId, String username, String password, String mobile) @ApiModelProperty("用户手机")
{ private String mobile;
this.userId = userId;
this.username = username; public UserEntity()
this.password = password; {
this.mobile = mobile;
} }
public Integer getUserId() public UserEntity(Integer userId, String username, String password, String mobile)
{ {
return userId; this.userId = userId;
} this.username = username;
this.password = password;
public void setUserId(Integer userId) this.mobile = mobile;
{ }
this.userId = userId;
} public Integer getUserId()
{
public String getUsername() return userId;
{ }
return username;
} public void setUserId(Integer userId)
{
public void setUsername(String username) this.userId = userId;
{ }
this.username = username;
} public String getUsername()
{
public String getPassword() return username;
{ }
return password;
} public void setUsername(String username)
{
public void setPassword(String password) this.username = username;
{ }
this.password = password;
} public String getPassword()
{
public String getMobile() return password;
{ }
return mobile;
} public void setPassword(String password)
{
public void setMobile(String mobile) this.password = password;
{ }
this.mobile = mobile;
} public String getMobile()
} {
return mobile;
}
public void setMobile(String mobile)
{
this.mobile = mobile;
}
}

View File

@@ -1,64 +1,125 @@
package com.ruoyi.web.core.config; package com.ruoyi.web.core.config;
import org.springframework.beans.factory.annotation.Autowired; import java.util.ArrayList;
import org.springframework.context.annotation.Bean; import java.util.List;
import org.springframework.context.annotation.Configuration; import org.springframework.beans.factory.annotation.Autowired;
import com.ruoyi.common.config.RuoYiConfig; import org.springframework.beans.factory.annotation.Value;
import io.swagger.v3.oas.models.Components; import org.springframework.context.annotation.Bean;
import io.swagger.v3.oas.models.OpenAPI; import org.springframework.context.annotation.Configuration;
import io.swagger.v3.oas.models.info.Contact; import com.ruoyi.common.config.RuoYiConfig;
import io.swagger.v3.oas.models.info.Info; import io.swagger.annotations.ApiOperation;
import io.swagger.v3.oas.models.security.SecurityRequirement; import io.swagger.models.auth.In;
import io.swagger.v3.oas.models.security.SecurityScheme; import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
/** import springfox.documentation.builders.RequestHandlerSelectors;
* Swagger2的接口配置 import springfox.documentation.service.ApiInfo;
* import springfox.documentation.service.ApiKey;
* @author ruoyi import springfox.documentation.service.AuthorizationScope;
*/ import springfox.documentation.service.Contact;
@Configuration import springfox.documentation.service.SecurityReference;
public class SwaggerConfig import springfox.documentation.service.SecurityScheme;
{ import springfox.documentation.spi.DocumentationType;
/** 系统基础配置 */ import springfox.documentation.spi.service.contexts.SecurityContext;
@Autowired import springfox.documentation.spring.web.plugins.Docket;
private RuoYiConfig ruoyiConfig;
/**
/** * Swagger2的接口配置
* 自定义的 OpenAPI 对象 *
*/ * @author ruoyi
@Bean */
public OpenAPI customOpenApi() @Configuration
{ public class SwaggerConfig
return new OpenAPI().components(new Components() {
// 设置认证的请求头 /** 系统基础配置 */
.addSecuritySchemes("apikey", securityScheme())) @Autowired
.addSecurityItem(new SecurityRequirement().addList("apikey")) private RuoYiConfig ruoyiConfig;
.info(getApiInfo());
} /** 是否开启swagger */
@Value("${swagger.enabled}")
@Bean private boolean enabled;
public SecurityScheme securityScheme()
{ /** 设置请求的统一前缀 */
return new SecurityScheme() @Value("${swagger.pathMapping}")
.type(SecurityScheme.Type.APIKEY) private String pathMapping;
.name("Authorization")
.in(SecurityScheme.In.HEADER) /**
.scheme("Bearer"); * 创建API
} */
@Bean
/** public Docket createRestApi()
* 添加摘要信息 {
*/ return new Docket(DocumentationType.OAS_30)
public Info getApiInfo() // 是否启用Swagger
{ .enable(enabled)
return new Info() // 用来创建该API的基本信息展示在文档的页面中自定义展示的信息
// 设置标题 .apiInfo(apiInfo())
.title("标题若依管理系统_接口文档") // 设置哪些接口暴露给Swagger展示
// 描述 .select()
.description("描述:用于管理集团旗下公司的人员信息,具体包括XXX,XXX模块...") // 扫描所有有注解的api用这种方式更灵活
// 作者信息 .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
.contact(new Contact().name(ruoyiConfig.getName())) // 扫描指定包中的swagger注解
// 版本 // .apis(RequestHandlerSelectors.basePackage("com.ruoyi.project.tool.swagger"))
.version("版本号:" + ruoyiConfig.getVersion()); // 扫描所有 .apis(RequestHandlerSelectors.any())
} .paths(PathSelectors.any())
} .build()
/* 设置安全模式swagger可以设置访问token */
.securitySchemes(securitySchemes())
.securityContexts(securityContexts())
.pathMapping(pathMapping);
}
/**
* 安全模式这里指定token通过Authorization头请求头传递
*/
private List<SecurityScheme> securitySchemes()
{
List<SecurityScheme> apiKeyList = new ArrayList<SecurityScheme>();
apiKeyList.add(new ApiKey("Authorization", "Authorization", In.HEADER.toValue()));
return apiKeyList;
}
/**
* 安全上下文
*/
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()
{
// 用ApiInfoBuilder进行定制
return new ApiInfoBuilder()
// 设置标题
.title("标题若依管理系统_接口文档")
// 描述
.description("描述:用于管理集团旗下公司的人员信息,具体包括XXX,XXX模块...")
// 作者信息
.contact(new Contact(ruoyiConfig.getName(), null, null))
// 版本
.version("版本号:" + ruoyiConfig.getVersion())
.build();
}
}

View File

@@ -0,0 +1,61 @@
# 数据源配置
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.cj.jdbc.Driver
druid:
# 主库数据源
master:
url: jdbc:mysql://localhost:3306/ry-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

View File

@@ -3,7 +3,7 @@ ruoyi:
# 名称 # 名称
name: RuoYi name: RuoYi
# 版本 # 版本
version: 3.9.1 version: 3.9.2
# 版权年份 # 版权年份
copyrightYear: 2026 copyrightYear: 2026
# 文件路径 示例( Windows配置D:/ruoyi/uploadPathLinux配置 /home/ruoyi/uploadPath # 文件路径 示例( Windows配置D:/ruoyi/uploadPathLinux配置 /home/ruoyi/uploadPath
@@ -49,6 +49,19 @@ 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配置
@@ -60,8 +73,8 @@ token:
# 令牌有效期默认30分钟 # 令牌有效期默认30分钟
expireTime: 30 expireTime: 30
# MyBatis Plus配置 # MyBatis配置
mybatis-plus: mybatis:
# 搜索指定包别名 # 搜索指定包别名
typeAliasesPackage: com.ruoyi.**.domain typeAliasesPackage: com.ruoyi.**.domain
# 配置mapper的扫描找到所有的mapper.xml映射文件 # 配置mapper的扫描找到所有的mapper.xml映射文件
@@ -75,14 +88,12 @@ pagehelper:
supportMethodsArguments: true supportMethodsArguments: true
params: count=countSql params: count=countSql
# Springdoc配置 # Swagger配置
springdoc: swagger:
api-docs: # 是否开启swagger
path: /v3/api-docs enabled: true
swagger-ui: # 请求前缀
enabled: true pathMapping: /dev-api
path: /swagger-ui.html
tags-sorter: alpha
# 防盗链配置 # 防盗链配置
referer: referer:

View File

@@ -1,24 +1,24 @@
Application Version: ${ruoyi.version} Application Version: ${ruoyi.version}
Spring Boot Version: ${spring-boot.version} Spring Boot Version: ${spring-boot.version}
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// _ooOoo_ // // _ooOoo_ //
// o8888888o // // o8888888o //
// 88" . "88 // // 88" . "88 //
// (| ^_^ |) // // (| ^_^ |) //
// O\ = /O // // O\ = /O //
// ____/`---'\____ // // ____/`---'\____ //
// .' \\| |// `. // // .' \\| |// `. //
// / \\||| : |||// \ // // / \\||| : |||// \ //
// / _||||| -:- |||||- \ // // / _||||| -:- |||||- \ //
// | | \\\ - /// | | // // | | \\\ - /// | | //
// | \_| ''\---/'' | | // // | \_| ''\---/'' | | //
// \ .-\__ `-` ___/-. / // // \ .-\__ `-` ___/-. / //
// ___`. .' /--.--\ `. . ___ // // ___`. .' /--.--\ `. . ___ //
// ."" '< `.___\_<|>_/___.' >'"". // // ."" '< `.___\_<|>_/___.' >'"". //
// | | : `- \`.;`\ _ /`;.`/ - ` : | | // // | | : `- \`.;`\ _ /`;.`/ - ` : | | //
// \ \ `-. \_ __\ /__ _/ .-` / / // // \ \ `-. \_ __\ /__ _/ .-` / / //
// ========`-.____`-.___\_____/___.-`____.-'======== // // ========`-.____`-.___\_____/___.-`____.-'======== //
// `=---=' // // `=---=' //
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ // // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //
// 佛祖保佑 永不宕机 永无BUG // // 佛祖保佑 永不宕机 永无BUG //
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////

View File

@@ -1,38 +1,38 @@
#错误消息 #错误消息
not.null=* 必须填写 not.null=* 必须填写
user.jcaptcha.error=验证码错误 user.jcaptcha.error=验证码错误
user.jcaptcha.expire=验证码已失效 user.jcaptcha.expire=验证码已失效
user.not.exists=用户不存在/密码错误 user.not.exists=用户不存在/密码错误
user.password.not.match=用户不存在/密码错误 user.password.not.match=用户不存在/密码错误
user.password.retry.limit.count=密码输入错误{0}次 user.password.retry.limit.count=密码输入错误{0}次
user.password.retry.limit.exceed=密码输入错误{0}次,帐户锁定{1}分钟 user.password.retry.limit.exceed=密码输入错误{0}次,帐户锁定{1}分钟
user.password.delete=对不起,您的账号已被删除 user.password.delete=对不起,您的账号已被删除
user.blocked=用户已封禁,请联系管理员 user.blocked=用户已封禁,请联系管理员
role.blocked=角色已封禁,请联系管理员 role.blocked=角色已封禁,请联系管理员
login.blocked=很遗憾访问IP已被列入系统黑名单 login.blocked=很遗憾访问IP已被列入系统黑名单
user.logout.success=退出成功 user.logout.success=退出成功
length.not.valid=长度必须在{min}到{max}个字符之间 length.not.valid=长度必须在{min}到{max}个字符之间
user.username.not.valid=* 2到20个汉字、字母、数字或下划线组成且必须以非数字开头 user.username.not.valid=* 2到20个汉字、字母、数字或下划线组成且必须以非数字开头
user.password.not.valid=* 5-50个字符 user.password.not.valid=* 5-50个字符
user.email.not.valid=邮箱格式错误 user.email.not.valid=邮箱格式错误
user.mobile.phone.number.not.valid=手机号格式错误 user.mobile.phone.number.not.valid=手机号格式错误
user.login.success=登录成功 user.login.success=登录成功
user.register.success=注册成功 user.register.success=注册成功
user.notfound=请重新登录 user.notfound=请重新登录
user.forcelogout=管理员强制退出,请重新登录 user.forcelogout=管理员强制退出,请重新登录
user.unknown.error=未知错误,请重新登录 user.unknown.error=未知错误,请重新登录
##文件上传消息 ##文件上传消息
upload.exceed.maxSize=上传的文件大小超出限制的文件大小!<br/>允许的文件最大大小是:{0}MB upload.exceed.maxSize=上传的文件大小超出限制的文件大小!<br/>允许的文件最大大小是:{0}MB
upload.filename.exceed.length=上传的文件名最长{0}个字符 upload.filename.exceed.length=上传的文件名最长{0}个字符
##权限 ##权限
no.permission=您没有数据的权限,请联系管理员添加权限 [{0}] no.permission=您没有数据的权限,请联系管理员添加权限 [{0}]
no.create.permission=您没有创建数据的权限,请联系管理员添加权限 [{0}] no.create.permission=您没有创建数据的权限,请联系管理员添加权限 [{0}]
no.update.permission=您没有修改数据的权限,请联系管理员添加权限 [{0}] no.update.permission=您没有修改数据的权限,请联系管理员添加权限 [{0}]
no.delete.permission=您没有删除数据的权限,请联系管理员添加权限 [{0}] no.delete.permission=您没有删除数据的权限,请联系管理员添加权限 [{0}]
no.export.permission=您没有导出数据的权限,请联系管理员添加权限 [{0}] no.export.permission=您没有导出数据的权限,请联系管理员添加权限 [{0}]
no.view.permission=您没有查看数据的权限,请联系管理员添加权限 [{0}] no.view.permission=您没有查看数据的权限,请联系管理员添加权限 [{0}]

View File

@@ -1,93 +1,93 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<configuration> <configuration>
<!-- 日志存放路径 --> <!-- 日志存放路径 -->
<property name="log.path" value="logs" /> <property name="log.path" value="logs" />
<!-- 日志输出格式 --> <!-- 日志输出格式 -->
<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" /> <property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />
<!-- 控制台输出 --> <!-- 控制台输出 -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender"> <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder> <encoder>
<pattern>${log.pattern}</pattern> <pattern>${log.pattern}</pattern>
</encoder> </encoder>
</appender> </appender>
<!-- 系统日志输出 --> <!-- 系统日志输出 -->
<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender"> <appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/sys-info.log</file> <file>${log.path}/sys-info.log</file>
<!-- 循环政策:基于时间创建日志文件 --> <!-- 循环政策:基于时间创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件名格式 --> <!-- 日志文件名格式 -->
<fileNamePattern>${log.path}/sys-info.%d{yyyy-MM-dd}.log</fileNamePattern> <fileNamePattern>${log.path}/sys-info.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 60天 --> <!-- 日志最大的历史 60天 -->
<maxHistory>60</maxHistory> <maxHistory>60</maxHistory>
</rollingPolicy> </rollingPolicy>
<encoder> <encoder>
<pattern>${log.pattern}</pattern> <pattern>${log.pattern}</pattern>
</encoder> </encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter"> <filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 过滤的级别 --> <!-- 过滤的级别 -->
<level>INFO</level> <level>INFO</level>
<!-- 匹配时的操作:接收(记录) --> <!-- 匹配时的操作:接收(记录) -->
<onMatch>ACCEPT</onMatch> <onMatch>ACCEPT</onMatch>
<!-- 不匹配时的操作:拒绝(不记录) --> <!-- 不匹配时的操作:拒绝(不记录) -->
<onMismatch>DENY</onMismatch> <onMismatch>DENY</onMismatch>
</filter> </filter>
</appender> </appender>
<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender"> <appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/sys-error.log</file> <file>${log.path}/sys-error.log</file>
<!-- 循环政策:基于时间创建日志文件 --> <!-- 循环政策:基于时间创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件名格式 --> <!-- 日志文件名格式 -->
<fileNamePattern>${log.path}/sys-error.%d{yyyy-MM-dd}.log</fileNamePattern> <fileNamePattern>${log.path}/sys-error.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 60天 --> <!-- 日志最大的历史 60天 -->
<maxHistory>60</maxHistory> <maxHistory>60</maxHistory>
</rollingPolicy> </rollingPolicy>
<encoder> <encoder>
<pattern>${log.pattern}</pattern> <pattern>${log.pattern}</pattern>
</encoder> </encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter"> <filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 过滤的级别 --> <!-- 过滤的级别 -->
<level>ERROR</level> <level>ERROR</level>
<!-- 匹配时的操作:接收(记录) --> <!-- 匹配时的操作:接收(记录) -->
<onMatch>ACCEPT</onMatch> <onMatch>ACCEPT</onMatch>
<!-- 不匹配时的操作:拒绝(不记录) --> <!-- 不匹配时的操作:拒绝(不记录) -->
<onMismatch>DENY</onMismatch> <onMismatch>DENY</onMismatch>
</filter> </filter>
</appender> </appender>
<!-- 用户访问日志输出 --> <!-- 用户访问日志输出 -->
<appender name="sys-user" class="ch.qos.logback.core.rolling.RollingFileAppender"> <appender name="sys-user" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/sys-user.log</file> <file>${log.path}/sys-user.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 按天回滚 daily --> <!-- 按天回滚 daily -->
<fileNamePattern>${log.path}/sys-user.%d{yyyy-MM-dd}.log</fileNamePattern> <fileNamePattern>${log.path}/sys-user.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 60天 --> <!-- 日志最大的历史 60天 -->
<maxHistory>60</maxHistory> <maxHistory>60</maxHistory>
</rollingPolicy> </rollingPolicy>
<encoder> <encoder>
<pattern>${log.pattern}</pattern> <pattern>${log.pattern}</pattern>
</encoder> </encoder>
</appender> </appender>
<!-- 系统模块日志级别控制 --> <!-- 系统模块日志级别控制 -->
<logger name="com.ruoyi" level="info" /> <logger name="com.ruoyi" level="info" />
<!-- Spring日志级别控制 --> <!-- Spring日志级别控制 -->
<logger name="org.springframework" level="warn" /> <logger name="org.springframework" level="warn" />
<root level="info"> <root level="info">
<appender-ref ref="console" /> <appender-ref ref="console" />
</root> </root>
<!--系统操作日志--> <!--系统操作日志-->
<root level="info"> <root level="info">
<appender-ref ref="file_info" /> <appender-ref ref="file_info" />
<appender-ref ref="file_error" /> <appender-ref ref="file_error" />
</root> </root>
<!--系统用户操作日志--> <!--系统用户操作日志-->
<logger name="sys-user" level="info"> <logger name="sys-user" level="info">
<appender-ref ref="sys-user"/> <appender-ref ref="sys-user"/>
</logger> </logger>
</configuration> </configuration>

View File

@@ -1,20 +1,20 @@
<?xml version="1.0" encoding="UTF-8" ?> <?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration <!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN" PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd"> "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration> <configuration>
<!-- 全局参数 --> <!-- 全局参数 -->
<settings> <settings>
<!-- 使全局的映射器启用或禁用缓存 --> <!-- 使全局的映射器启用或禁用缓存 -->
<setting name="cacheEnabled" value="true" /> <setting name="cacheEnabled" value="true" />
<!-- 允许JDBC 支持自动生成主键 --> <!-- 允许JDBC 支持自动生成主键 -->
<setting name="useGeneratedKeys" value="true" /> <setting name="useGeneratedKeys" value="true" />
<!-- 配置默认的执行器.SIMPLE就是普通执行器;REUSE执行器会重用预处理语句(prepared statements);BATCH执行器将重用语句并执行批量更新 --> <!-- 配置默认的执行器.SIMPLE就是普通执行器;REUSE执行器会重用预处理语句(prepared statements);BATCH执行器将重用语句并执行批量更新 -->
<setting name="defaultExecutorType" value="SIMPLE" /> <setting name="defaultExecutorType" value="SIMPLE" />
<!-- 指定 MyBatis 所用日志的具体实现 --> <!-- 指定 MyBatis 所用日志的具体实现 -->
<setting name="logImpl" value="SLF4J" /> <setting name="logImpl" value="SLF4J" />
<!-- 使用驼峰命名法转换字段 --> <!-- 使用驼峰命名法转换字段 -->
<!-- <setting name="mapUnderscoreToCamelCase" value="true"/> --> <!-- <setting name="mapUnderscoreToCamelCase" value="true"/> -->
</settings> </settings>
</configuration> </configuration>

View File

@@ -1,19 +0,0 @@
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
});
};

View File

@@ -1,44 +0,0 @@
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());
}
}

View File

@@ -1,40 +0,0 @@
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");
}
}

View File

@@ -1,72 +0,0 @@
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);
}
}

View File

@@ -1,50 +0,0 @@
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());
}
}

View File

@@ -1,113 +0,0 @@
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()));
}
}

View File

@@ -1,130 +1,118 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" <project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent> <parent>
<artifactId>ruoyi</artifactId> <artifactId>ruoyi</artifactId>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<version>3.9.1</version> <version>3.9.2</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<artifactId>ruoyi-common</artifactId> <artifactId>ruoyi-common</artifactId>
<description> <description>
common通用工具 common通用工具
</description> </description>
<dependencies> <dependencies>
<!-- Spring框架基本的核心工具 --> <!-- Spring框架基本的核心工具 -->
<dependency> <dependency>
<groupId>org.springframework</groupId> <groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId> <artifactId>spring-context-support</artifactId>
</dependency> </dependency>
<!-- SpringWeb模块 --> <!-- SpringWeb模块 -->
<dependency> <dependency>
<groupId>org.springframework</groupId> <groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId> <artifactId>spring-web</artifactId>
</dependency> </dependency>
<!-- spring security 安全认证 --> <!-- spring security 安全认证 -->
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId> <artifactId>spring-boot-starter-security</artifactId>
</dependency> </dependency>
<!-- pagehelper 分页插件 --> <!-- pagehelper 分页插件 -->
<dependency> <dependency>
<groupId>com.github.pagehelper</groupId> <groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId> <artifactId>pagehelper-spring-boot-starter</artifactId>
</dependency> </dependency>
<!-- 自定义验证注解 --> <!-- 自定义验证注解 -->
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId> <artifactId>spring-boot-starter-validation</artifactId>
</dependency> </dependency>
<!--常用工具类 --> <!--常用工具类 -->
<dependency> <dependency>
<groupId>org.apache.commons</groupId> <groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId> <artifactId>commons-lang3</artifactId>
</dependency> </dependency>
<!-- JSON工具类 --> <!-- JSON工具类 -->
<dependency> <dependency>
<groupId>com.fasterxml.jackson.core</groupId> <groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId> <artifactId>jackson-databind</artifactId>
</dependency> </dependency>
<!-- 阿里JSON解析器 --> <!-- 阿里JSON解析器 -->
<dependency> <dependency>
<groupId>com.alibaba.fastjson2</groupId> <groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId> <artifactId>fastjson2</artifactId>
</dependency> </dependency>
<!-- io常用工具类 --> <!-- io常用工具类 -->
<dependency> <dependency>
<groupId>commons-io</groupId> <groupId>commons-io</groupId>
<artifactId>commons-io</artifactId> <artifactId>commons-io</artifactId>
</dependency> </dependency>
<!-- excel工具 --> <!-- excel工具 -->
<dependency> <dependency>
<groupId>org.apache.poi</groupId> <groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId> <artifactId>poi-ooxml</artifactId>
</dependency> </dependency>
<!-- Token生成与解析--> <!-- Token生成与解析-->
<dependency> <dependency>
<groupId>io.jsonwebtoken</groupId> <groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId> <artifactId>jjwt</artifactId>
</dependency> </dependency>
<!-- Jaxb --> <!-- Jaxb -->
<dependency> <dependency>
<groupId>javax.xml.bind</groupId> <groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId> <artifactId>jaxb-api</artifactId>
</dependency> </dependency>
<!-- 解析客户端操作系统、浏览器等 --> <!-- redis 缓存操作 -->
<dependency> <dependency>
<groupId>nl.basjes.parse.useragent</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>yauaa</artifactId> <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency> </dependency>
<!-- servlet包 --> <!-- pool 对象池 -->
<dependency> <dependency>
<groupId>jakarta.servlet</groupId> <groupId>org.apache.commons</groupId>
<artifactId>jakarta.servlet-api</artifactId> <artifactId>commons-pool2</artifactId>
</dependency> </dependency>
<!-- ruoyi-springboot3 / mybatis-plus 配置 -->
<dependency> <!-- 解析客户端操作系统、浏览器等 -->
<groupId>org.mybatis</groupId> <dependency>
<artifactId>mybatis</artifactId> <groupId>nl.basjes.parse.useragent</groupId>
<version>3.5.16</version> <artifactId>yauaa</artifactId>
</dependency> </dependency>
<dependency> <!-- servlet包 -->
<groupId>com.baomidou</groupId> <dependency>
<artifactId>mybatis-plus-spring-boot3-starter</artifactId> <groupId>javax.servlet</groupId>
<version>3.5.10</version> <artifactId>javax.servlet-api</artifactId>
</dependency> </dependency>
<dependency> </dependencies>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-jsqlparser</artifactId> </project>
<version>3.5.10</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@@ -1,19 +1,19 @@
package com.ruoyi.common.annotation; package com.ruoyi.common.annotation;
import java.lang.annotation.Documented; import java.lang.annotation.Documented;
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;
import java.lang.annotation.Target; import java.lang.annotation.Target;
/** /**
* 匿名访问不鉴权注解 * 匿名访问不鉴权注解
* *
* @author ruoyi * @author ruoyi
*/ */
@Target({ ElementType.METHOD, ElementType.TYPE }) @Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Documented @Documented
public @interface Anonymous public @interface Anonymous
{ {
} }

View File

@@ -1,33 +1,43 @@
package com.ruoyi.common.annotation; package com.ruoyi.common.annotation;
import java.lang.annotation.Documented; import java.lang.annotation.Documented;
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;
import java.lang.annotation.Target; import java.lang.annotation.Target;
/** /**
* 数据权限过滤注解 * 数据权限过滤注解
* *
* @author ruoyi * @author ruoyi
*/ */
@Target(ElementType.METHOD) @Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Documented @Documented
public @interface DataScope public @interface DataScope
{ {
/** /**
* 部门表的别名 * 用户表的别名
*/ */
public String deptAlias() default ""; public String userAlias() default "";
/** /**
* 用户表的别名 * 部门表的别名
*/ */
public String userAlias() default ""; public String deptAlias() default "";
/** /**
* 权限字符(用于多个角色匹配符合要求的权限)默认根据权限注解@ss获取多个权限用逗号分隔开来 * 用户字段名
*/ */
public String permission() default ""; public String userField() default "user_id";
}
/**
* 部门字段名
*/
public String deptField() default "dept_id";
/**
* 权限字符(用于多个角色匹配符合要求的权限)默认根据权限注解@ss获取多个权限用逗号分隔开来
*/
public String permission() default "";
}

View File

@@ -1,28 +1,28 @@
package com.ruoyi.common.annotation; package com.ruoyi.common.annotation;
import java.lang.annotation.Documented; import java.lang.annotation.Documented;
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited; import java.lang.annotation.Inherited;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import com.ruoyi.common.enums.DataSourceType; import com.ruoyi.common.enums.DataSourceType;
/** /**
* 自定义多数据源切换注解 * 自定义多数据源切换注解
* *
* 优先级:先方法,后类,如果方法覆盖了类上的数据源类型,以方法的为准,否则以类上的为准 * 优先级:先方法,后类,如果方法覆盖了类上的数据源类型,以方法的为准,否则以类上的为准
* *
* @author ruoyi * @author ruoyi
*/ */
@Target({ ElementType.METHOD, ElementType.TYPE }) @Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Documented @Documented
@Inherited @Inherited
public @interface DataSource public @interface DataSource
{ {
/** /**
* 切换数据源名称 * 切换数据源名称
*/ */
public DataSourceType value() default DataSourceType.MASTER; public DataSourceType value() default DataSourceType.MASTER;
} }

View File

@@ -1,198 +1,197 @@
package com.ruoyi.common.annotation; package com.ruoyi.common.annotation;
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;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import java.math.BigDecimal; import java.math.BigDecimal;
import org.apache.poi.ss.usermodel.HorizontalAlignment; import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors; import org.apache.poi.ss.usermodel.IndexedColors;
import com.ruoyi.common.utils.poi.ExcelHandlerAdapter; import com.ruoyi.common.utils.poi.ExcelHandlerAdapter;
/** /**
* 自定义导出Excel数据注解 * 自定义导出Excel数据注解
* *
* @author ruoyi * @author ruoyi
*/ */
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD) @Target(ElementType.FIELD)
public @interface Excel public @interface Excel
{ {
/** /**
* 导出时在excel中排序 * 导出时在excel中排序
*/ */
public int sort() default Integer.MAX_VALUE; public int sort() default Integer.MAX_VALUE;
/** /**
* 导出到Excel中的名字. * 导出到Excel中的名字.
*/ */
public String name() default ""; public String name() default "";
/** /**
* 日期格式, 如: yyyy-MM-dd * 日期格式, 如: yyyy-MM-dd
*/ */
public String dateFormat() default ""; public String dateFormat() default "";
/** /**
* 如果是字典类型请设置字典的type值 (如: sys_user_sex) * 如果是字典类型请设置字典的type值 (如: sys_user_sex)
*/ */
public String dictType() default ""; public String dictType() default "";
/** /**
* 读取内容转表达式 (如: 0=男,1=女,2=未知) * 读取内容转表达式 (如: 0=男,1=女,2=未知)
*/ */
public String readConverterExp() default ""; public String readConverterExp() default "";
/** /**
* 分隔符,读取字符串组内容 * 分隔符,读取字符串组内容
*/ */
public String separator() default ","; public String separator() default ",";
/** /**
* BigDecimal 精度 默认:-1(默认不开启BigDecimal格式化) * BigDecimal 精度 默认:-1(默认不开启BigDecimal格式化)
*/ */
public int scale() default -1; public int scale() default -1;
/** /**
* 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;
/**
/** * 导出时在excel中每个列的高度
* 导出时在excel中每个列的高度 */
*/ public double height() default 14;
public double height() default 14;
/**
/** * 导出时在excel中每个列的宽度
* 导出时在excel中每个列的宽度 */
*/ public double width() default 16;
public double width() default 16;
/**
/** * 文字后缀,如% 90 变成90%
* 文字后缀,如% 90 变成90% */
*/ public String suffix() default "";
public String suffix() default "";
/**
/** * 当值为空时,字段的默认值
* 当值为空时,字段的默认值 */
*/ public String defaultValue() default "";
public String defaultValue() default "";
/**
/** * 提示信息
* 提示信息 */
*/ public String prompt() default "";
public String prompt() default "";
/**
/** * 是否允许内容换行
* 是否允许内容换行 */
*/ public boolean wrapText() default false;
public boolean wrapText() default false;
/**
/** * 设置只能选择不能输入的列内容.
* 设置只能选择不能输入的列内容. */
*/ public String[] combo() default {};
public String[] combo() default {};
/**
/** * 是否从字典读数据到combo,默认不读取,如读取需要设置dictType注解.
* 是否从字典读数据到combo,默认不读取,如读取需要设置dictType注解. */
*/ public boolean comboReadDict() default false;
public boolean comboReadDict() default false;
/**
/** * 是否需要纵向合并单元格,应对需求:含有list集合单元格)
* 是否需要纵向合并单元格,应对需求:含有list集合单元格) */
*/ public boolean needMerge() default false;
public boolean needMerge() default false;
/**
/** * 是否导出数据,应对需求:有时我们需要导出一份模板,这是标题需要但内容需要用户手工填写.
* 是否导出数据,应对需求:有时我们需要导出一份模板,这是标题需要但内容需要用户手工填写. */
*/ public boolean isExport() default true;
public boolean isExport() default true;
/**
/** * 另一个类中的属性名称,支持多级获取,以小数点隔开
* 另一个类中的属性名称,支持多级获取,以小数点隔开 */
*/ public String targetAttr() default "";
public String targetAttr() default "";
/**
/** * 是否自动统计数据,在最后追加一行统计数据总和
* 是否自动统计数据,在最后追加一行统计数据总和 */
*/ public boolean isStatistics() default false;
public boolean isStatistics() default false;
/**
/** * 导出类型0数字 1字符串 2图片
* 导出类型0数字 1字符串 2图片 */
*/ public ColumnType cellType() default ColumnType.STRING;
public ColumnType cellType() default ColumnType.STRING;
/**
/** * 导出列头背景颜色
* 导出列头背景颜色 */
*/ public IndexedColors headerBackgroundColor() default IndexedColors.GREY_50_PERCENT;
public IndexedColors headerBackgroundColor() default IndexedColors.GREY_50_PERCENT;
/**
/** * 导出列头字体颜色
* 导出列头字体颜色 */
*/ public IndexedColors headerColor() default IndexedColors.WHITE;
public IndexedColors headerColor() default IndexedColors.WHITE;
/**
/** * 导出单元格背景颜色
* 导出单元格背景颜色 */
*/ public IndexedColors backgroundColor() default IndexedColors.WHITE;
public IndexedColors backgroundColor() default IndexedColors.WHITE;
/**
/** * 导出单元格字体颜色
* 导出单元格字体颜色 */
*/ public IndexedColors color() default IndexedColors.BLACK;
public IndexedColors color() default IndexedColors.BLACK;
/**
/** * 导出字段对齐方式
* 导出字段对齐方式 */
*/ public HorizontalAlignment align() default HorizontalAlignment.CENTER;
public HorizontalAlignment align() default HorizontalAlignment.CENTER;
/**
/** * 自定义数据处理器
* 自定义数据处理器 */
*/ public Class<?> handler() default ExcelHandlerAdapter.class;
public Class<?> handler() default ExcelHandlerAdapter.class;
/**
/** * 自定义数据处理器参数
* 自定义数据处理器参数 */
*/ public String[] args() default {};
public String[] args() default {};
/**
/** * 字段类型0导出导入1仅导出2仅导入
* 字段类型0导出导入1仅导出2仅导入 */
*/ Type type() default Type.ALL;
Type type() default Type.ALL;
public enum Type
public enum Type {
{ ALL(0), EXPORT(1), IMPORT(2);
ALL(0), EXPORT(1), IMPORT(2); private final int value;
private final int value;
Type(int value)
Type(int value) {
{ this.value = value;
this.value = value; }
}
public int value()
public int value() {
{ return this.value;
return this.value; }
} }
}
public enum ColumnType
public enum ColumnType {
{ NUMERIC(0), STRING(1), IMAGE(2), TEXT(3);
NUMERIC(0), STRING(1), IMAGE(2), TEXT(3); private final int value;
private final int value;
ColumnType(int value)
ColumnType(int value) {
{ this.value = value;
this.value = value; }
}
public int value()
public int value() {
{ return this.value;
return this.value; }
} }
}
} }

View File

@@ -1,18 +1,18 @@
package com.ruoyi.common.annotation; package com.ruoyi.common.annotation;
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;
import java.lang.annotation.Target; import java.lang.annotation.Target;
/** /**
* Excel注解集 * Excel注解集
* *
* @author ruoyi * @author ruoyi
*/ */
@Target(ElementType.FIELD) @Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
public @interface Excels public @interface Excels
{ {
public Excel[] value(); public Excel[] value();
} }

View File

@@ -1,51 +1,51 @@
package com.ruoyi.common.annotation; package com.ruoyi.common.annotation;
import java.lang.annotation.Documented; import java.lang.annotation.Documented;
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;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.enums.OperatorType; import com.ruoyi.common.enums.OperatorType;
/** /**
* 自定义操作日志记录注解 * 自定义操作日志记录注解
* *
* @author ruoyi * @author ruoyi
* *
*/ */
@Target({ ElementType.PARAMETER, ElementType.METHOD }) @Target({ ElementType.PARAMETER, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Documented @Documented
public @interface Log public @interface Log
{ {
/** /**
* 模块 * 模块
*/ */
public String title() default ""; public String title() default "";
/** /**
* 功能 * 功能
*/ */
public BusinessType businessType() default BusinessType.OTHER; public BusinessType businessType() default BusinessType.OTHER;
/** /**
* 操作人类别 * 操作人类别
*/ */
public OperatorType operatorType() default OperatorType.MANAGE; public OperatorType operatorType() default OperatorType.MANAGE;
/** /**
* 是否保存请求的参数 * 是否保存请求的参数
*/ */
public boolean isSaveRequestData() default true; public boolean isSaveRequestData() default true;
/** /**
* 是否保存响应的参数 * 是否保存响应的参数
*/ */
public boolean isSaveResponseData() default true; public boolean isSaveResponseData() default true;
/** /**
* 排除指定的请求参数 * 排除指定的请求参数
*/ */
public String[] excludeParamNames() default {}; public String[] excludeParamNames() default {};
} }

View File

@@ -1,40 +1,40 @@
package com.ruoyi.common.annotation; package com.ruoyi.common.annotation;
import java.lang.annotation.Documented; import java.lang.annotation.Documented;
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;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import com.ruoyi.common.constant.CacheConstants; import com.ruoyi.common.constant.CacheConstants;
import com.ruoyi.common.enums.LimitType; import com.ruoyi.common.enums.LimitType;
/** /**
* 限流注解 * 限流注解
* *
* @author ruoyi * @author ruoyi
*/ */
@Target(ElementType.METHOD) @Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Documented @Documented
public @interface RateLimiter public @interface RateLimiter
{ {
/** /**
* 限流key * 限流key
*/ */
public String key() default CacheConstants.RATE_LIMIT_KEY; public String key() default CacheConstants.RATE_LIMIT_KEY;
/** /**
* 限流时间,单位秒 * 限流时间,单位秒
*/ */
public int time() default 60; public int time() default 60;
/** /**
* 限流次数 * 限流次数
*/ */
public int count() default 100; public int count() default 100;
/** /**
* 限流类型 * 限流类型
*/ */
public LimitType limitType() default LimitType.DEFAULT; public LimitType limitType() default LimitType.DEFAULT;
} }

View File

@@ -1,31 +1,31 @@
package com.ruoyi.common.annotation; package com.ruoyi.common.annotation;
import java.lang.annotation.Documented; import java.lang.annotation.Documented;
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited; import java.lang.annotation.Inherited;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
/** /**
* 自定义注解防止表单重复提交 * 自定义注解防止表单重复提交
* *
* @author ruoyi * @author ruoyi
* *
*/ */
@Inherited @Inherited
@Target(ElementType.METHOD) @Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Documented @Documented
public @interface RepeatSubmit public @interface RepeatSubmit
{ {
/** /**
* 间隔时间(ms),小于此时间视为重复提交 * 间隔时间(ms),小于此时间视为重复提交
*/ */
public int interval() default 5000; public int interval() default 5000;
/** /**
* 提示消息 * 提示消息
*/ */
public String message() default "不允许重复提交,请稍候再试"; public String message() default "不允许重复提交,请稍候再试";
} }

View File

@@ -1,122 +1,122 @@
package com.ruoyi.common.config; package com.ruoyi.common.config;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
/** /**
* 读取项目相关配置 * 读取项目相关配置
* *
* @author ruoyi * @author ruoyi
*/ */
@Component @Component
@ConfigurationProperties(prefix = "ruoyi") @ConfigurationProperties(prefix = "ruoyi")
public class RuoYiConfig public class RuoYiConfig
{ {
/** 项目名称 */ /** 项目名称 */
private String name; private String name;
/** 版本 */ /** 版本 */
private String version; private String version;
/** 版权年份 */ /** 版权年份 */
private String copyrightYear; private String copyrightYear;
/** 上传路径 */ /** 上传路径 */
private static String profile; private static String profile;
/** 获取地址开关 */ /** 获取地址开关 */
private static boolean addressEnabled; private static boolean addressEnabled;
/** 验证码类型 */ /** 验证码类型 */
private static String captchaType; private static String captchaType;
public String getName() public String getName()
{ {
return name; return name;
} }
public void setName(String name) public void setName(String name)
{ {
this.name = name; this.name = name;
} }
public String getVersion() public String getVersion()
{ {
return version; return version;
} }
public void setVersion(String version) public void setVersion(String version)
{ {
this.version = version; this.version = version;
} }
public String getCopyrightYear() public String getCopyrightYear()
{ {
return copyrightYear; return copyrightYear;
} }
public void setCopyrightYear(String copyrightYear) public void setCopyrightYear(String copyrightYear)
{ {
this.copyrightYear = copyrightYear; this.copyrightYear = copyrightYear;
} }
public static String getProfile() public static String getProfile()
{ {
return profile; return profile;
} }
public void setProfile(String profile) public void setProfile(String profile)
{ {
RuoYiConfig.profile = profile; RuoYiConfig.profile = profile;
} }
public static boolean isAddressEnabled() public static boolean isAddressEnabled()
{ {
return addressEnabled; return addressEnabled;
} }
public void setAddressEnabled(boolean addressEnabled) public void setAddressEnabled(boolean addressEnabled)
{ {
RuoYiConfig.addressEnabled = addressEnabled; RuoYiConfig.addressEnabled = addressEnabled;
} }
public static String getCaptchaType() { public static String getCaptchaType() {
return captchaType; return captchaType;
} }
public void setCaptchaType(String captchaType) { public void setCaptchaType(String captchaType) {
RuoYiConfig.captchaType = captchaType; RuoYiConfig.captchaType = captchaType;
} }
/** /**
* 获取导入上传路径 * 获取导入上传路径
*/ */
public static String getImportPath() public static String getImportPath()
{ {
return getProfile() + "/import"; return getProfile() + "/import";
} }
/** /**
* 获取头像上传路径 * 获取头像上传路径
*/ */
public static String getAvatarPath() public static String getAvatarPath()
{ {
return getProfile() + "/avatar"; return getProfile() + "/avatar";
} }
/** /**
* 获取下载路径 * 获取下载路径
*/ */
public static String getDownloadPath() public static String getDownloadPath()
{ {
return getProfile() + "/download/"; return getProfile() + "/download/";
} }
/** /**
* 获取上传路径 * 获取上传路径
*/ */
public static String getUploadPath() public static String getUploadPath()
{ {
return getProfile() + "/upload"; return getProfile() + "/upload";
} }
} }

View File

@@ -1,44 +1,44 @@
package com.ruoyi.common.constant; package com.ruoyi.common.constant;
/** /**
* 缓存的key 常量 * 缓存的key 常量
* *
* @author ruoyi * @author ruoyi
*/ */
public class CacheConstants public class CacheConstants
{ {
/** /**
* 登录用户 redis key * 登录用户 redis key
*/ */
public static final String LOGIN_TOKEN_KEY = "login_tokens:"; public static final String LOGIN_TOKEN_KEY = "login_tokens:";
/** /**
* 验证码 redis key * 验证码 redis key
*/ */
public static final String CAPTCHA_CODE_KEY = "captcha_codes:"; public static final String CAPTCHA_CODE_KEY = "captcha_codes:";
/** /**
* 参数管理 cache key * 参数管理 cache key
*/ */
public static final String SYS_CONFIG_KEY = "sys_config:"; public static final String SYS_CONFIG_KEY = "sys_config:";
/** /**
* 字典管理 cache key * 字典管理 cache key
*/ */
public static final String SYS_DICT_KEY = "sys_dict:"; public static final String SYS_DICT_KEY = "sys_dict:";
/** /**
* 防重提交 redis key * 防重提交 redis key
*/ */
public static final String REPEAT_SUBMIT_KEY = "repeat_submit:"; public static final String REPEAT_SUBMIT_KEY = "repeat_submit:";
/** /**
* 限流 redis key * 限流 redis key
*/ */
public static final String RATE_LIMIT_KEY = "rate_limit:"; public static final String RATE_LIMIT_KEY = "rate_limit:";
/** /**
* 登录账户密码错误次数 redis key * 登录账户密码错误次数 redis key
*/ */
public static final String PWD_ERR_CNT_KEY = "pwd_err_cnt:"; public static final String PWD_ERR_CNT_KEY = "pwd_err_cnt:";
} }

View File

@@ -1,173 +1,204 @@
package com.ruoyi.common.constant; package com.ruoyi.common.constant;
import java.util.Locale; import java.util.Locale;
import io.jsonwebtoken.Claims; import io.jsonwebtoken.Claims;
/** /**
* 通用常量信息 * 通用常量信息
* *
* @author ruoyi * @author ruoyi
*/ */
public class Constants public class Constants
{ {
/** /**
* UTF-8 字符集 * UTF-8 字符集
*/ */
public static final String UTF8 = "UTF-8"; public static final String UTF8 = "UTF-8";
/** /**
* GBK 字符集 * GBK 字符集
*/ */
public static final String GBK = "GBK"; public static final String GBK = "GBK";
/** /**
* 系统语言 * 系统语言
*/ */
public static final Locale DEFAULT_LOCALE = Locale.SIMPLIFIED_CHINESE; public static final Locale DEFAULT_LOCALE = Locale.SIMPLIFIED_CHINESE;
/** /**
* www主域 * www主域
*/ */
public static final String WWW = "www."; public static final String WWW = "www.";
/** /**
* http请求 * http请求
*/ */
public static final String HTTP = "http://"; public static final String HTTP = "http://";
/** /**
* https请求 * https请求
*/ */
public static final String HTTPS = "https://"; public static final String HTTPS = "https://";
/** /**
* 通用成功标识 * 通用成功标识
*/ */
public static final String SUCCESS = "0"; public static final String SUCCESS = "0";
/** /**
* 通用失败标识 * 通用失败标识
*/ */
public static final String FAIL = "1"; public static final String FAIL = "1";
/** /**
* 登录成功 * 登录成功
*/ */
public static final String LOGIN_SUCCESS = "Success"; public static final String LOGIN_SUCCESS = "Success";
/** /**
* 注销 * 注销
*/ */
public static final String LOGOUT = "Logout"; public static final String LOGOUT = "Logout";
/** /**
* 注册 * 注册
*/ */
public static final String REGISTER = "Register"; public static final String REGISTER = "Register";
/** /**
* 登录失败 * 登录失败
*/ */
public static final String LOGIN_FAIL = "Error"; public static final String LOGIN_FAIL = "Error";
/** /**
* 所有权限标识 * 所有权限标识
*/ */
public static final String ALL_PERMISSION = "*:*:*"; public static final String ALL_PERMISSION = "*:*:*";
/** /**
* 管理员角色权限标识 * 管理员角色权限标识
*/ */
public static final String SUPER_ADMIN = "admin"; public static final String SUPER_ADMIN = "admin";
/** /**
* 角色权限分隔符 * 角色权限分隔符
*/ */
public static final String ROLE_DELIMITER = ","; public static final String ROLE_DELIMITER = ",";
/** /**
* 权限标识分隔符 * 权限标识分隔符
*/ */
public static final String PERMISSION_DELIMITER = ","; public static final String PERMISSION_DELIMITER = ",";
/** /**
* 验证码有效期(分钟) * 验证码有效期(分钟)
*/ */
public static final Integer CAPTCHA_EXPIRATION = 2; public static final Integer CAPTCHA_EXPIRATION = 2;
/** /**
* 令牌 * 令牌
*/ */
public static final String TOKEN = "token"; public static final String TOKEN = "token";
/** /**
* 令牌前缀 * 令牌前缀
*/ */
public static final String TOKEN_PREFIX = "Bearer "; public static final String TOKEN_PREFIX = "Bearer ";
/** /**
* 令牌前缀 * 令牌前缀
*/ */
public static final String LOGIN_USER_KEY = "login_user_key"; public static final String LOGIN_USER_KEY = "login_user_key";
/** /**
* 用户ID * 用户ID
*/ */
public static final String JWT_USERID = "userid"; public static final String JWT_USERID = "userid";
/** /**
* 用户名称 * 用户名称
*/ */
public static final String JWT_USERNAME = Claims.SUBJECT; public static final String JWT_USERNAME = Claims.SUBJECT;
/** /**
* 用户头像 * 用户头像
*/ */
public static final String JWT_AVATAR = "avatar"; public static final String JWT_AVATAR = "avatar";
/** /**
* 创建时间 * 创建时间
*/ */
public static final String JWT_CREATED = "created"; public static final String JWT_CREATED = "created";
/** /**
* 用户权限 * 用户权限
*/ */
public static final String JWT_AUTHORITIES = "authorities"; public static final String JWT_AUTHORITIES = "authorities";
/** /**
* 资源映射路径 前缀 * 资源映射路径 前缀
*/ */
public static final String RESOURCE_PREFIX = "/profile"; public static final String RESOURCE_PREFIX = "/profile";
/** /**
* RMI 远程方法调用 * RMI 远程方法调用
*/ */
public static final String LOOKUP_RMI = "rmi:"; public static final String LOOKUP_RMI = "rmi:";
/** /**
* LDAP 远程方法调用 * LDAP 远程方法调用
*/ */
public static final String LOOKUP_LDAP = "ldap:"; public static final String LOOKUP_LDAP = "ldap:";
/** /**
* LDAPS 远程方法调用 * LDAPS 远程方法调用
*/ */
public static final String LOOKUP_LDAPS = "ldaps:"; public static final String LOOKUP_LDAPS = "ldaps:";
/** /**
* 自动识别json对象白名单配置仅允许解析的包名范围越小越安全 * 自动识别json对象白名单配置仅允许解析的包名范围越小越安全
*/ */
public static final String[] JSON_WHITELIST_STR = { "com.ruoyi" }; public static final String[] JSON_WHITELIST_STR = { "com.ruoyi" };
/** /**
* 定时任务白名单配置(仅允许访问的包名,如其他需要可以自行添加) * 定时任务白名单配置(仅允许访问的包名,如其他需要可以自行添加)
*/ */
public static final String[] JOB_WHITELIST_STR = { "com.ruoyi.quartz.task" }; public static final String[] JOB_WHITELIST_STR = { "com.ruoyi.quartz.task" };
/** /**
* 定时任务违规的字符 * 定时任务违规的字符
*/ */
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";
}
}

View File

@@ -1,117 +1,120 @@
package com.ruoyi.common.constant; package com.ruoyi.common.constant;
/** /**
* 代码生成通用常量 * 代码生成通用常量
* *
* @author ruoyi * @author ruoyi
*/ */
public class GenConstants public class GenConstants
{ {
/** 单表(增删改查) */ /** 单表(增删改查) */
public static final String TPL_CRUD = "crud"; public static final String TPL_CRUD = "crud";
/** 树表(增删改查) */ /** 树表(增删改查) */
public static final String TPL_TREE = "tree"; public static final String TPL_TREE = "tree";
/** 主子表(增删改查) */ /** 主子表(增删改查) */
public static final String TPL_SUB = "sub"; public static final String TPL_SUB = "sub";
/** 树编码字段 */ /** 树编码字段 */
public static final String TREE_CODE = "treeCode"; public static final String TREE_CODE = "treeCode";
/** 树父编码字段 */ /** 树父编码字段 */
public static final String TREE_PARENT_CODE = "treeParentCode"; public static final String TREE_PARENT_CODE = "treeParentCode";
/** 树名称字段 */ /** 树名称字段 */
public static final String TREE_NAME = "treeName"; public static final String TREE_NAME = "treeName";
/** 上级菜单ID字段 */ /** 上级菜单ID字段 */
public static final String PARENT_MENU_ID = "parentMenuId"; public static final String PARENT_MENU_ID = "parentMenuId";
/** 上级菜单名称字段 */ /** 上级菜单名称字段 */
public static final String PARENT_MENU_NAME = "parentMenuName"; public static final String PARENT_MENU_NAME = "parentMenuName";
/** 数据库字符串类型 */ /** 生成详情页开关 */
public static final String[] COLUMNTYPE_STR = { "char", "varchar", "nvarchar", "varchar2" }; public static final String GEN_VIEW = "genView";
/** 数据库文本类型 */ /** 数据库字符串类型 */
public static final String[] COLUMNTYPE_TEXT = { "tinytext", "text", "mediumtext", "longtext" }; public static final String[] COLUMNTYPE_STR = { "char", "varchar", "nvarchar", "varchar2" };
/** 数据库时间类型 */ /** 数据库文本类型 */
public static final String[] COLUMNTYPE_TIME = { "datetime", "time", "date", "timestamp" }; public static final String[] COLUMNTYPE_TEXT = { "tinytext", "text", "mediumtext", "longtext" };
/** 数据库数字类型 */ /** 数据库时间类型 */
public static final String[] COLUMNTYPE_NUMBER = { "tinyint", "smallint", "mediumint", "int", "number", "integer", public static final String[] COLUMNTYPE_TIME = { "datetime", "time", "date", "timestamp" };
"bit", "bigint", "float", "double", "decimal" };
/** 数据库数字类型 */
/** 页面不需要编辑字段 */ public static final String[] COLUMNTYPE_NUMBER = { "tinyint", "smallint", "mediumint", "int", "number", "integer",
public static final String[] COLUMNNAME_NOT_EDIT = { "id", "create_by", "create_time", "del_flag" }; "bit", "bigint", "float", "double", "decimal" };
/** 页面不需要显示的列表字段 */ /** 页面不需要编辑字段 */
public static final String[] COLUMNNAME_NOT_LIST = { "id", "create_by", "create_time", "del_flag", "update_by", public static final String[] COLUMNNAME_NOT_EDIT = { "id", "create_by", "create_time", "del_flag" };
"update_time" };
/** 页面不需要显示的列表字段 */
/** 页面不需要查询字段 */ public static final String[] COLUMNNAME_NOT_LIST = { "id", "create_by", "create_time", "del_flag", "update_by",
public static final String[] COLUMNNAME_NOT_QUERY = { "id", "create_by", "create_time", "del_flag", "update_by", "update_time" };
"update_time", "remark" };
/** 页面不需要查询字段 */
/** Entity基类字段 */ public static final String[] COLUMNNAME_NOT_QUERY = { "id", "create_by", "create_time", "del_flag", "update_by",
public static final String[] BASE_ENTITY = { "createBy", "createTime", "updateBy", "updateTime", "remark" }; "update_time", "remark" };
/** Tree基类字段 */ /** Entity基类字段 */
public static final String[] TREE_ENTITY = { "parentName", "parentId", "orderNum", "ancestors", "children" }; public static final String[] BASE_ENTITY = { "createBy", "createTime", "updateBy", "updateTime", "remark" };
/** 文本框 */ /** Tree基类字段 */
public static final String HTML_INPUT = "input"; public static final String[] TREE_ENTITY = { "parentName", "parentId", "orderNum", "ancestors", "children" };
/** 文本 */ /** 文本 */
public static final String HTML_TEXTAREA = "textarea"; public static final String HTML_INPUT = "input";
/** 下拉框 */ /** 文本域 */
public static final String HTML_SELECT = "select"; public static final String HTML_TEXTAREA = "textarea";
/** 单选框 */ /** 下拉框 */
public static final String HTML_RADIO = "radio"; public static final String HTML_SELECT = "select";
/** 选框 */ /** 选框 */
public static final String HTML_CHECKBOX = "checkbox"; public static final String HTML_RADIO = "radio";
/** 日期控件 */ /** 复选框 */
public static final String HTML_DATETIME = "datetime"; public static final String HTML_CHECKBOX = "checkbox";
/** 图片上传控件 */ /** 日期控件 */
public static final String HTML_IMAGE_UPLOAD = "imageUpload"; public static final String HTML_DATETIME = "datetime";
/** 文件上传控件 */ /** 图片上传控件 */
public static final String HTML_FILE_UPLOAD = "fileUpload"; public static final String HTML_IMAGE_UPLOAD = "imageUpload";
/** 富文本控件 */ /** 文件上传控件 */
public static final String HTML_EDITOR = "editor"; public static final String HTML_FILE_UPLOAD = "fileUpload";
/** 字符串类型 */ /** 富文本控件 */
public static final String TYPE_STRING = "String"; public static final String HTML_EDITOR = "editor";
/** 型 */ /** 字符串类型 */
public static final String TYPE_INTEGER = "Integer"; public static final String TYPE_STRING = "String";
/** 整型 */ /** 整型 */
public static final String TYPE_LONG = "Long"; public static final String TYPE_INTEGER = "Integer";
/** 浮点型 */ /** 长整型 */
public static final String TYPE_DOUBLE = "Double"; public static final String TYPE_LONG = "Long";
/** 高精度计算类型 */ /** 浮点型 */
public static final String TYPE_BIGDECIMAL = "BigDecimal"; public static final String TYPE_DOUBLE = "Double";
/** 时间类型 */ /** 高精度计算类型 */
public static final String TYPE_DATE = "Date"; public static final String TYPE_BIGDECIMAL = "BigDecimal";
/** 模糊查询 */ /** 时间类型 */
public static final String QUERY_LIKE = "LIKE"; public static final String TYPE_DATE = "Date";
/** 相等查询 */ /** 模糊查询 */
public static final String QUERY_EQ = "EQ"; public static final String QUERY_LIKE = "LIKE";
/** 需要 */ /** 相等查询 */
public static final String REQUIRE = "1"; public static final String QUERY_EQ = "EQ";
}
/** 需要 */
public static final String REQUIRE = "1";
}

View File

@@ -1,94 +1,94 @@
package com.ruoyi.common.constant; package com.ruoyi.common.constant;
/** /**
* 返回状态码 * 返回状态码
* *
* @author ruoyi * @author ruoyi
*/ */
public class HttpStatus public class HttpStatus
{ {
/** /**
* 操作成功 * 操作成功
*/ */
public static final int SUCCESS = 200; public static final int SUCCESS = 200;
/** /**
* 对象创建成功 * 对象创建成功
*/ */
public static final int CREATED = 201; public static final int CREATED = 201;
/** /**
* 请求已经被接受 * 请求已经被接受
*/ */
public static final int ACCEPTED = 202; public static final int ACCEPTED = 202;
/** /**
* 操作已经执行成功,但是没有返回数据 * 操作已经执行成功,但是没有返回数据
*/ */
public static final int NO_CONTENT = 204; public static final int NO_CONTENT = 204;
/** /**
* 资源已被移除 * 资源已被移除
*/ */
public static final int MOVED_PERM = 301; public static final int MOVED_PERM = 301;
/** /**
* 重定向 * 重定向
*/ */
public static final int SEE_OTHER = 303; public static final int SEE_OTHER = 303;
/** /**
* 资源没有被修改 * 资源没有被修改
*/ */
public static final int NOT_MODIFIED = 304; public static final int NOT_MODIFIED = 304;
/** /**
* 参数列表错误(缺少,格式不匹配) * 参数列表错误(缺少,格式不匹配)
*/ */
public static final int BAD_REQUEST = 400; public static final int BAD_REQUEST = 400;
/** /**
* 未授权 * 未授权
*/ */
public static final int UNAUTHORIZED = 401; public static final int UNAUTHORIZED = 401;
/** /**
* 访问受限,授权过期 * 访问受限,授权过期
*/ */
public static final int FORBIDDEN = 403; public static final int FORBIDDEN = 403;
/** /**
* 资源,服务未找到 * 资源,服务未找到
*/ */
public static final int NOT_FOUND = 404; public static final int NOT_FOUND = 404;
/** /**
* 不允许的http方法 * 不允许的http方法
*/ */
public static final int BAD_METHOD = 405; public static final int BAD_METHOD = 405;
/** /**
* 资源冲突,或者资源被锁 * 资源冲突,或者资源被锁
*/ */
public static final int CONFLICT = 409; public static final int CONFLICT = 409;
/** /**
* 不支持的数据,媒体类型 * 不支持的数据,媒体类型
*/ */
public static final int UNSUPPORTED_TYPE = 415; public static final int UNSUPPORTED_TYPE = 415;
/** /**
* 系统内部错误 * 系统内部错误
*/ */
public static final int ERROR = 500; public static final int ERROR = 500;
/** /**
* 接口未实现 * 接口未实现
*/ */
public static final int NOT_IMPLEMENTED = 501; public static final int NOT_IMPLEMENTED = 501;
/** /**
* 系统警告消息 * 系统警告消息
*/ */
public static final int WARN = 601; public static final int WARN = 601;
} }

View File

@@ -1,50 +1,50 @@
package com.ruoyi.common.constant; package com.ruoyi.common.constant;
/** /**
* 任务调度通用常量 * 任务调度通用常量
* *
* @author ruoyi * @author ruoyi
*/ */
public class ScheduleConstants public class ScheduleConstants
{ {
public static final String TASK_CLASS_NAME = "TASK_CLASS_NAME"; public static final String TASK_CLASS_NAME = "TASK_CLASS_NAME";
/** 执行目标key */ /** 执行目标key */
public static final String TASK_PROPERTIES = "TASK_PROPERTIES"; public static final String TASK_PROPERTIES = "TASK_PROPERTIES";
/** 默认 */ /** 默认 */
public static final String MISFIRE_DEFAULT = "0"; public static final String MISFIRE_DEFAULT = "0";
/** 立即触发执行 */ /** 立即触发执行 */
public static final String MISFIRE_IGNORE_MISFIRES = "1"; public static final String MISFIRE_IGNORE_MISFIRES = "1";
/** 触发一次执行 */ /** 触发一次执行 */
public static final String MISFIRE_FIRE_AND_PROCEED = "2"; public static final String MISFIRE_FIRE_AND_PROCEED = "2";
/** 不触发立即执行 */ /** 不触发立即执行 */
public static final String MISFIRE_DO_NOTHING = "3"; public static final String MISFIRE_DO_NOTHING = "3";
public enum Status public enum Status
{ {
/** /**
* 正常 * 正常
*/ */
NORMAL("0"), NORMAL("0"),
/** /**
* 暂停 * 暂停
*/ */
PAUSE("1"); PAUSE("1");
private String value; private String value;
private Status(String value) private Status(String value)
{ {
this.value = value; this.value = value;
} }
public String getValue() public String getValue()
{ {
return value; return value;
} }
} }
} }

View File

@@ -1,81 +1,81 @@
package com.ruoyi.common.constant; package com.ruoyi.common.constant;
/** /**
* 用户常量信息 * 用户常量信息
* *
* @author ruoyi * @author ruoyi
*/ */
public class UserConstants public class UserConstants
{ {
/** /**
* 平台内系统用户的唯一标志 * 平台内系统用户的唯一标志
*/ */
public static final String SYS_USER = "SYS_USER"; public static final String SYS_USER = "SYS_USER";
/** 正常状态 */ /** 正常状态 */
public static final String NORMAL = "0"; public static final String NORMAL = "0";
/** 异常状态 */ /** 异常状态 */
public static final String EXCEPTION = "1"; public static final String EXCEPTION = "1";
/** 用户封禁状态 */ /** 用户封禁状态 */
public static final String USER_DISABLE = "1"; public static final String USER_DISABLE = "1";
/** 角色正常状态 */ /** 角色正常状态 */
public static final String ROLE_NORMAL = "0"; public static final String ROLE_NORMAL = "0";
/** 角色封禁状态 */ /** 角色封禁状态 */
public static final String ROLE_DISABLE = "1"; public static final String ROLE_DISABLE = "1";
/** 部门正常状态 */ /** 部门正常状态 */
public static final String DEPT_NORMAL = "0"; public static final String DEPT_NORMAL = "0";
/** 部门停用状态 */ /** 部门停用状态 */
public static final String DEPT_DISABLE = "1"; public static final String DEPT_DISABLE = "1";
/** 字典正常状态 */ /** 字典正常状态 */
public static final String DICT_NORMAL = "0"; public static final String DICT_NORMAL = "0";
/** 是否为系统默认(是) */ /** 是否为系统默认(是) */
public static final String YES = "Y"; public static final String YES = "Y";
/** 是否菜单外链(是) */ /** 是否菜单外链(是) */
public static final String YES_FRAME = "0"; public static final String YES_FRAME = "0";
/** 是否菜单外链(否) */ /** 是否菜单外链(否) */
public static final String NO_FRAME = "1"; public static final String NO_FRAME = "1";
/** 菜单类型(目录) */ /** 菜单类型(目录) */
public static final String TYPE_DIR = "M"; public static final String TYPE_DIR = "M";
/** 菜单类型(菜单) */ /** 菜单类型(菜单) */
public static final String TYPE_MENU = "C"; public static final String TYPE_MENU = "C";
/** 菜单类型(按钮) */ /** 菜单类型(按钮) */
public static final String TYPE_BUTTON = "F"; public static final String TYPE_BUTTON = "F";
/** Layout组件标识 */ /** Layout组件标识 */
public final static String LAYOUT = "Layout"; public final static String LAYOUT = "Layout";
/** ParentView组件标识 */ /** ParentView组件标识 */
public final static String PARENT_VIEW = "ParentView"; public final static String PARENT_VIEW = "ParentView";
/** InnerLink组件标识 */ /** InnerLink组件标识 */
public final static String INNER_LINK = "InnerLink"; public final static String INNER_LINK = "InnerLink";
/** 校验是否唯一的返回标识 */ /** 校验是否唯一的返回标识 */
public final static boolean UNIQUE = true; public final static boolean UNIQUE = true;
public final static boolean NOT_UNIQUE = false; public final static boolean NOT_UNIQUE = false;
/** /**
* 用户名长度限制 * 用户名长度限制
*/ */
public static final int USERNAME_MIN_LENGTH = 2; public static final int USERNAME_MIN_LENGTH = 2;
public static final int USERNAME_MAX_LENGTH = 20; public static final int USERNAME_MAX_LENGTH = 20;
/** /**
* 密码长度限制 * 密码长度限制
*/ */
public static final int PASSWORD_MIN_LENGTH = 5; public static final int PASSWORD_MIN_LENGTH = 5;
public static final int PASSWORD_MAX_LENGTH = 20; public static final int PASSWORD_MAX_LENGTH = 20;
} }

View File

@@ -1,8 +1,27 @@
package com.ruoyi.common.core.cache; package com.ruoyi.common.core.cache;
record InMemoryCacheEntry(Object value, Long expireAtMillis) public class InMemoryCacheEntry
{ {
boolean isExpired(long now) private final Object value;
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;
} }

View File

@@ -1,12 +1,58 @@
package com.ruoyi.common.core.cache; package com.ruoyi.common.core.cache;
public record InMemoryCacheStats( public class 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;
}
} }

View File

@@ -1,8 +1,12 @@
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;
@@ -10,7 +14,6 @@ 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
@@ -36,7 +39,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.value(); return entry == null ? null : (T) entry.getValue();
} }
public boolean hasKey(String key) public boolean hasKey(String key)
@@ -63,12 +66,13 @@ public class InMemoryCacheStore
{ {
purgeExpiredEntries(); purgeExpiredEntries();
Set<String> matchedKeys = new TreeSet<>(); Set<String> matchedKeys = new TreeSet<>();
entries.forEach((key, value) -> { for (Map.Entry<String, InMemoryCacheEntry> entry : entries.entrySet())
if (matches(pattern, key)) {
if (matches(pattern, entry.getKey()))
{ {
matchedKeys.add(key); matchedKeys.add(entry.getKey());
} }
}); }
return matchedKeys; return matchedKeys;
} }
@@ -76,9 +80,24 @@ 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));
return entries.computeIfPresent(key, (cacheKey, entry) -> entry.isExpired(System.currentTimeMillis()) while (true)
? null {
: new InMemoryCacheEntry(entry.value(), expireAtMillis)) != null; InMemoryCacheEntry currentEntry = entries.get(key);
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)
@@ -93,11 +112,11 @@ public class InMemoryCacheStore
{ {
return -2L; return -2L;
} }
if (entry.expireAtMillis() == null) if (entry.getExpireAtMillis() == null)
{ {
return -1L; return -1L;
} }
long remainingMillis = Math.max(0L, entry.expireAtMillis() - System.currentTimeMillis()); long remainingMillis = Math.max(0L, entry.getExpireAtMillis() - 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;
} }
@@ -109,10 +128,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.value()) + 1L; long nextValue = missingOrExpired ? 1L : toLong(currentEntry.getValue()) + 1L;
Long expireAtMillis = missingOrExpired || currentEntry.expireAtMillis() == null Long expireAtMillis = (missingOrExpired || currentEntry.getExpireAtMillis() == null)
? now + Math.max(0L, unit.toMillis(timeout)) ? now + Math.max(0L, unit.toMillis(timeout))
: currentEntry.expireAtMillis(); : currentEntry.getExpireAtMillis();
if (missingOrExpired && currentEntry != null) if (missingOrExpired && currentEntry != null)
{ {
expiredCount.incrementAndGet(); expiredCount.incrementAndGet();
@@ -142,6 +161,7 @@ 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);
@@ -178,6 +198,7 @@ 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);
@@ -189,15 +210,28 @@ public class InMemoryCacheStore
set(key, new HashSet<>(dataSet)); set(key, new HashSet<>(dataSet));
} }
public <T> java.util.List<T> getList(String key) @SuppressWarnings("unchecked")
public <T> List<T> getList(String key)
{ {
java.util.List<T> value = get(key); List<T> value = get(key);
return value == null ? null : new java.util.ArrayList<>(value); return value == null ? null : new ArrayList<>(value);
} }
public <T> void putList(String key, java.util.List<T> dataList) public <T> void putList(String key, List<T> dataList)
{ {
set(key, new java.util.ArrayList<>(dataList)); set(key, new 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)
@@ -227,12 +261,13 @@ public class InMemoryCacheStore
private void purgeExpiredEntries() private void purgeExpiredEntries()
{ {
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
entries.forEach((key, entry) -> { for (Map.Entry<String, InMemoryCacheEntry> entry : entries.entrySet())
if (entry.isExpired(now)) {
if (entry.getValue().isExpired(now))
{ {
removeExpiredEntry(key, entry); removeExpiredEntry(entry.getKey(), entry.getValue());
} }
}); }
} }
private void removeExpiredEntry(String key, InMemoryCacheEntry expectedEntry) private void removeExpiredEntry(String key, InMemoryCacheEntry expectedEntry)
@@ -258,20 +293,10 @@ public class InMemoryCacheStore
private long toLong(Object value) private long toLong(Object value)
{ {
if (value instanceof Number number) if (value instanceof Number)
{ {
return number.longValue(); return ((Number) value).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);
}
} }

View File

@@ -1,202 +1,202 @@
package com.ruoyi.common.core.controller; package com.ruoyi.common.core.controller;
import java.beans.PropertyEditorSupport; import java.beans.PropertyEditorSupport;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.web.bind.WebDataBinder; import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder; import org.springframework.web.bind.annotation.InitBinder;
import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo; import com.github.pagehelper.PageInfo;
import com.ruoyi.common.constant.HttpStatus; import com.ruoyi.common.constant.HttpStatus;
import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.model.LoginUser; import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.page.PageDomain; import com.ruoyi.common.core.page.PageDomain;
import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.page.TableSupport; import com.ruoyi.common.core.page.TableSupport;
import com.ruoyi.common.utils.DateUtils; import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.PageUtils; import com.ruoyi.common.utils.PageUtils;
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.sql.SqlUtil; import com.ruoyi.common.utils.sql.SqlUtil;
/** /**
* web层通用数据处理 * web层通用数据处理
* *
* @author ruoyi * @author ruoyi
*/ */
public class BaseController public class BaseController
{ {
protected final Logger logger = LoggerFactory.getLogger(this.getClass()); protected final Logger logger = LoggerFactory.getLogger(this.getClass());
/** /**
* 将前台传递过来的日期格式的字符串自动转化为Date类型 * 将前台传递过来的日期格式的字符串自动转化为Date类型
*/ */
@InitBinder @InitBinder
public void initBinder(WebDataBinder binder) public void initBinder(WebDataBinder binder)
{ {
// Date 类型转换 // Date 类型转换
binder.registerCustomEditor(Date.class, new PropertyEditorSupport() binder.registerCustomEditor(Date.class, new PropertyEditorSupport()
{ {
@Override @Override
public void setAsText(String text) public void setAsText(String text)
{ {
setValue(DateUtils.parseDate(text)); setValue(DateUtils.parseDate(text));
} }
}); });
} }
/** /**
* 设置请求分页数据 * 设置请求分页数据
*/ */
protected void startPage() protected void startPage()
{ {
PageUtils.startPage(); PageUtils.startPage();
} }
/** /**
* 设置请求排序数据 * 设置请求排序数据
*/ */
protected void startOrderBy() protected void startOrderBy()
{ {
PageDomain pageDomain = TableSupport.buildPageRequest(); PageDomain pageDomain = TableSupport.buildPageRequest();
if (StringUtils.isNotEmpty(pageDomain.getOrderBy())) if (StringUtils.isNotEmpty(pageDomain.getOrderBy()))
{ {
String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy()); String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy());
PageHelper.orderBy(orderBy); PageHelper.orderBy(orderBy);
} }
} }
/** /**
* 清理分页的线程变量 * 清理分页的线程变量
*/ */
protected void clearPage() protected void clearPage()
{ {
PageUtils.clearPage(); PageUtils.clearPage();
} }
/** /**
* 响应请求分页数据 * 响应请求分页数据
*/ */
@SuppressWarnings({ "rawtypes", "unchecked" }) @SuppressWarnings({ "rawtypes", "unchecked" })
protected TableDataInfo getDataTable(List<?> list) protected TableDataInfo getDataTable(List<?> list)
{ {
TableDataInfo rspData = new TableDataInfo(); TableDataInfo rspData = new TableDataInfo();
rspData.setCode(HttpStatus.SUCCESS); rspData.setCode(HttpStatus.SUCCESS);
rspData.setMsg("查询成功"); rspData.setMsg("查询成功");
rspData.setRows(list); rspData.setRows(list);
rspData.setTotal(new PageInfo(list).getTotal()); rspData.setTotal(new PageInfo(list).getTotal());
return rspData; return rspData;
} }
/** /**
* 返回成功 * 返回成功
*/ */
public AjaxResult success() public AjaxResult success()
{ {
return AjaxResult.success(); return AjaxResult.success();
} }
/** /**
* 返回失败消息 * 返回失败消息
*/ */
public AjaxResult error() public AjaxResult error()
{ {
return AjaxResult.error(); return AjaxResult.error();
} }
/** /**
* 返回成功消息 * 返回成功消息
*/ */
public AjaxResult success(String message) public AjaxResult success(String message)
{ {
return AjaxResult.success(message); return AjaxResult.success(message);
} }
/** /**
* 返回成功消息 * 返回成功消息
*/ */
public AjaxResult success(Object data) public AjaxResult success(Object data)
{ {
return AjaxResult.success(data); return AjaxResult.success(data);
} }
/** /**
* 返回失败消息 * 返回失败消息
*/ */
public AjaxResult error(String message) public AjaxResult error(String message)
{ {
return AjaxResult.error(message); return AjaxResult.error(message);
} }
/** /**
* 返回警告消息 * 返回警告消息
*/ */
public AjaxResult warn(String message) public AjaxResult warn(String message)
{ {
return AjaxResult.warn(message); return AjaxResult.warn(message);
} }
/** /**
* 响应返回结果 * 响应返回结果
* *
* @param rows 影响行数 * @param rows 影响行数
* @return 操作结果 * @return 操作结果
*/ */
protected AjaxResult toAjax(int rows) protected AjaxResult toAjax(int rows)
{ {
return rows > 0 ? AjaxResult.success() : AjaxResult.error(); return rows > 0 ? AjaxResult.success() : AjaxResult.error();
} }
/** /**
* 响应返回结果 * 响应返回结果
* *
* @param result 结果 * @param result 结果
* @return 操作结果 * @return 操作结果
*/ */
protected AjaxResult toAjax(boolean result) protected AjaxResult toAjax(boolean result)
{ {
return result ? success() : error(); return result ? success() : error();
} }
/** /**
* 页面跳转 * 页面跳转
*/ */
public String redirect(String url) public String redirect(String url)
{ {
return StringUtils.format("redirect:{}", url); return StringUtils.format("redirect:{}", url);
} }
/** /**
* 获取用户缓存信息 * 获取用户缓存信息
*/ */
public LoginUser getLoginUser() public LoginUser getLoginUser()
{ {
return SecurityUtils.getLoginUser(); return SecurityUtils.getLoginUser();
} }
/** /**
* 获取登录用户id * 获取登录用户id
*/ */
public Long getUserId() public Long getUserId()
{ {
return getLoginUser().getUserId(); return getLoginUser().getUserId();
} }
/** /**
* 获取登录部门id * 获取登录部门id
*/ */
public Long getDeptId() public Long getDeptId()
{ {
return getLoginUser().getDeptId(); return getLoginUser().getDeptId();
} }
/** /**
* 获取登录用户名 * 获取登录用户名
*/ */
public String getUsername() public String getUsername()
{ {
return getLoginUser().getUsername(); return getLoginUser().getUsername();
} }
} }

View File

@@ -1,216 +1,216 @@
package com.ruoyi.common.core.domain; package com.ruoyi.common.core.domain;
import java.util.HashMap; import java.util.HashMap;
import java.util.Objects; import java.util.Objects;
import com.ruoyi.common.constant.HttpStatus; import com.ruoyi.common.constant.HttpStatus;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.StringUtils;
/** /**
* 操作消息提醒 * 操作消息提醒
* *
* @author ruoyi * @author ruoyi
*/ */
public class AjaxResult extends HashMap<String, Object> public class AjaxResult extends HashMap<String, Object>
{ {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
/** 状态码 */ /** 状态码 */
public static final String CODE_TAG = "code"; public static final String CODE_TAG = "code";
/** 返回内容 */ /** 返回内容 */
public static final String MSG_TAG = "msg"; public static final String MSG_TAG = "msg";
/** 数据对象 */ /** 数据对象 */
public static final String DATA_TAG = "data"; public static final String DATA_TAG = "data";
/** /**
* 初始化一个新创建的 AjaxResult 对象,使其表示一个空消息。 * 初始化一个新创建的 AjaxResult 对象,使其表示一个空消息。
*/ */
public AjaxResult() public AjaxResult()
{ {
} }
/** /**
* 初始化一个新创建的 AjaxResult 对象 * 初始化一个新创建的 AjaxResult 对象
* *
* @param code 状态码 * @param code 状态码
* @param msg 返回内容 * @param msg 返回内容
*/ */
public AjaxResult(int code, String msg) public AjaxResult(int code, String msg)
{ {
super.put(CODE_TAG, code); super.put(CODE_TAG, code);
super.put(MSG_TAG, msg); super.put(MSG_TAG, msg);
} }
/** /**
* 初始化一个新创建的 AjaxResult 对象 * 初始化一个新创建的 AjaxResult 对象
* *
* @param code 状态码 * @param code 状态码
* @param msg 返回内容 * @param msg 返回内容
* @param data 数据对象 * @param data 数据对象
*/ */
public AjaxResult(int code, String msg, Object data) public AjaxResult(int code, String msg, Object data)
{ {
super.put(CODE_TAG, code); super.put(CODE_TAG, code);
super.put(MSG_TAG, msg); super.put(MSG_TAG, msg);
if (StringUtils.isNotNull(data)) if (StringUtils.isNotNull(data))
{ {
super.put(DATA_TAG, data); super.put(DATA_TAG, data);
} }
} }
/** /**
* 返回成功消息 * 返回成功消息
* *
* @return 成功消息 * @return 成功消息
*/ */
public static AjaxResult success() public static AjaxResult success()
{ {
return AjaxResult.success("操作成功"); return AjaxResult.success("操作成功");
} }
/** /**
* 返回成功数据 * 返回成功数据
* *
* @return 成功消息 * @return 成功消息
*/ */
public static AjaxResult success(Object data) public static AjaxResult success(Object data)
{ {
return AjaxResult.success("操作成功", data); return AjaxResult.success("操作成功", data);
} }
/** /**
* 返回成功消息 * 返回成功消息
* *
* @param msg 返回内容 * @param msg 返回内容
* @return 成功消息 * @return 成功消息
*/ */
public static AjaxResult success(String msg) public static AjaxResult success(String msg)
{ {
return AjaxResult.success(msg, null); return AjaxResult.success(msg, null);
} }
/** /**
* 返回成功消息 * 返回成功消息
* *
* @param msg 返回内容 * @param msg 返回内容
* @param data 数据对象 * @param data 数据对象
* @return 成功消息 * @return 成功消息
*/ */
public static AjaxResult success(String msg, Object data) public static AjaxResult success(String msg, Object data)
{ {
return new AjaxResult(HttpStatus.SUCCESS, msg, data); return new AjaxResult(HttpStatus.SUCCESS, msg, data);
} }
/** /**
* 返回警告消息 * 返回警告消息
* *
* @param msg 返回内容 * @param msg 返回内容
* @return 警告消息 * @return 警告消息
*/ */
public static AjaxResult warn(String msg) public static AjaxResult warn(String msg)
{ {
return AjaxResult.warn(msg, null); return AjaxResult.warn(msg, null);
} }
/** /**
* 返回警告消息 * 返回警告消息
* *
* @param msg 返回内容 * @param msg 返回内容
* @param data 数据对象 * @param data 数据对象
* @return 警告消息 * @return 警告消息
*/ */
public static AjaxResult warn(String msg, Object data) public static AjaxResult warn(String msg, Object data)
{ {
return new AjaxResult(HttpStatus.WARN, msg, data); return new AjaxResult(HttpStatus.WARN, msg, data);
} }
/** /**
* 返回错误消息 * 返回错误消息
* *
* @return 错误消息 * @return 错误消息
*/ */
public static AjaxResult error() public static AjaxResult error()
{ {
return AjaxResult.error("操作失败"); return AjaxResult.error("操作失败");
} }
/** /**
* 返回错误消息 * 返回错误消息
* *
* @param msg 返回内容 * @param msg 返回内容
* @return 错误消息 * @return 错误消息
*/ */
public static AjaxResult error(String msg) public static AjaxResult error(String msg)
{ {
return AjaxResult.error(msg, null); return AjaxResult.error(msg, null);
} }
/** /**
* 返回错误消息 * 返回错误消息
* *
* @param msg 返回内容 * @param msg 返回内容
* @param data 数据对象 * @param data 数据对象
* @return 错误消息 * @return 错误消息
*/ */
public static AjaxResult error(String msg, Object data) public static AjaxResult error(String msg, Object data)
{ {
return new AjaxResult(HttpStatus.ERROR, msg, data); return new AjaxResult(HttpStatus.ERROR, msg, data);
} }
/** /**
* 返回错误消息 * 返回错误消息
* *
* @param code 状态码 * @param code 状态码
* @param msg 返回内容 * @param msg 返回内容
* @return 错误消息 * @return 错误消息
*/ */
public static AjaxResult error(int code, String msg) public static AjaxResult error(int code, String msg)
{ {
return new AjaxResult(code, msg, null); return new AjaxResult(code, msg, null);
} }
/** /**
* 是否为成功消息 * 是否为成功消息
* *
* @return 结果 * @return 结果
*/ */
public boolean isSuccess() public boolean isSuccess()
{ {
return Objects.equals(HttpStatus.SUCCESS, this.get(CODE_TAG)); return Objects.equals(HttpStatus.SUCCESS, this.get(CODE_TAG));
} }
/** /**
* 是否为警告消息 * 是否为警告消息
* *
* @return 结果 * @return 结果
*/ */
public boolean isWarn() public boolean isWarn()
{ {
return Objects.equals(HttpStatus.WARN, this.get(CODE_TAG)); return Objects.equals(HttpStatus.WARN, this.get(CODE_TAG));
} }
/** /**
* 是否为错误消息 * 是否为错误消息
* *
* @return 结果 * @return 结果
*/ */
public boolean isError() public boolean isError()
{ {
return Objects.equals(HttpStatus.ERROR, this.get(CODE_TAG)); return Objects.equals(HttpStatus.ERROR, this.get(CODE_TAG));
} }
/** /**
* 方便链式调用 * 方便链式调用
* *
* @param key 键 * @param key 键
* @param value 值 * @param value 值
* @return 数据对象 * @return 数据对象
*/ */
@Override @Override
public AjaxResult put(String key, Object value) public AjaxResult put(String key, Object value)
{ {
super.put(key, value); super.put(key, value);
return this; return this;
} }
} }

View File

@@ -1,118 +1,118 @@
package com.ruoyi.common.core.domain; package com.ruoyi.common.core.domain;
import java.io.Serializable; import java.io.Serializable;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude;
/** /**
* Entity基类 * Entity基类
* *
* @author ruoyi * @author ruoyi
*/ */
public class BaseEntity implements Serializable public class BaseEntity implements Serializable
{ {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
/** 搜索值 */ /** 搜索值 */
@JsonIgnore @JsonIgnore
private String searchValue; private String searchValue;
/** 创建者 */ /** 创建者 */
private String createBy; private String createBy;
/** 创建时间 */ /** 创建时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime; private Date createTime;
/** 更新者 */ /** 更新者 */
private String updateBy; private String updateBy;
/** 更新时间 */ /** 更新时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateTime; private Date updateTime;
/** 备注 */ /** 备注 */
private String remark; private String remark;
/** 请求参数 */ /** 请求参数 */
@JsonInclude(JsonInclude.Include.NON_EMPTY) @JsonInclude(JsonInclude.Include.NON_EMPTY)
private Map<String, Object> params; private Map<String, Object> params;
public String getSearchValue() public String getSearchValue()
{ {
return searchValue; return searchValue;
} }
public void setSearchValue(String searchValue) public void setSearchValue(String searchValue)
{ {
this.searchValue = searchValue; this.searchValue = searchValue;
} }
public String getCreateBy() public String getCreateBy()
{ {
return createBy; return createBy;
} }
public void setCreateBy(String createBy) public void setCreateBy(String createBy)
{ {
this.createBy = createBy; this.createBy = createBy;
} }
public Date getCreateTime() public Date getCreateTime()
{ {
return createTime; return createTime;
} }
public void setCreateTime(Date createTime) public void setCreateTime(Date createTime)
{ {
this.createTime = createTime; this.createTime = createTime;
} }
public String getUpdateBy() public String getUpdateBy()
{ {
return updateBy; return updateBy;
} }
public void setUpdateBy(String updateBy) public void setUpdateBy(String updateBy)
{ {
this.updateBy = updateBy; this.updateBy = updateBy;
} }
public Date getUpdateTime() public Date getUpdateTime()
{ {
return updateTime; return updateTime;
} }
public void setUpdateTime(Date updateTime) public void setUpdateTime(Date updateTime)
{ {
this.updateTime = updateTime; this.updateTime = updateTime;
} }
public String getRemark() public String getRemark()
{ {
return remark; return remark;
} }
public void setRemark(String remark) public void setRemark(String remark)
{ {
this.remark = remark; this.remark = remark;
} }
public Map<String, Object> getParams() public Map<String, Object> getParams()
{ {
if (params == null) if (params == null)
{ {
params = new HashMap<>(); params = new HashMap<>();
} }
return params; return params;
} }
public void setParams(Map<String, Object> params) public void setParams(Map<String, Object> params)
{ {
this.params = params; this.params = params;
} }
} }

View File

@@ -1,79 +1,79 @@
package com.ruoyi.common.core.domain; package com.ruoyi.common.core.domain;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
/** /**
* Tree基类 * Tree基类
* *
* @author ruoyi * @author ruoyi
*/ */
public class TreeEntity extends BaseEntity public class TreeEntity extends BaseEntity
{ {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
/** 父菜单名称 */ /** 父菜单名称 */
private String parentName; private String parentName;
/** 父菜单ID */ /** 父菜单ID */
private Long parentId; private Long parentId;
/** 显示顺序 */ /** 显示顺序 */
private Integer orderNum; private Integer orderNum;
/** 祖级列表 */ /** 祖级列表 */
private String ancestors; private String ancestors;
/** 子部门 */ /** 子部门 */
private List<?> children = new ArrayList<>(); private List<?> children = new ArrayList<>();
public String getParentName() public String getParentName()
{ {
return parentName; return parentName;
} }
public void setParentName(String parentName) public void setParentName(String parentName)
{ {
this.parentName = parentName; this.parentName = parentName;
} }
public Long getParentId() public Long getParentId()
{ {
return parentId; return parentId;
} }
public void setParentId(Long parentId) public void setParentId(Long parentId)
{ {
this.parentId = parentId; this.parentId = parentId;
} }
public Integer getOrderNum() public Integer getOrderNum()
{ {
return orderNum; return orderNum;
} }
public void setOrderNum(Integer orderNum) public void setOrderNum(Integer orderNum)
{ {
this.orderNum = orderNum; this.orderNum = orderNum;
} }
public String getAncestors() public String getAncestors()
{ {
return ancestors; return ancestors;
} }
public void setAncestors(String ancestors) public void setAncestors(String ancestors)
{ {
this.ancestors = ancestors; this.ancestors = ancestors;
} }
public List<?> getChildren() public List<?> getChildren()
{ {
return children; return children;
} }
public void setChildren(List<?> children) public void setChildren(List<?> children)
{ {
this.children = children; this.children = children;
} }
} }

View File

@@ -1,93 +1,93 @@
package com.ruoyi.common.core.domain; package com.ruoyi.common.core.domain;
import java.io.Serializable; import java.io.Serializable;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude;
import com.ruoyi.common.constant.UserConstants; import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.domain.entity.SysDept; import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysMenu; import com.ruoyi.common.core.domain.entity.SysMenu;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.StringUtils;
/** /**
* Treeselect树结构实体类 * Treeselect树结构实体类
* *
* @author ruoyi * @author ruoyi
*/ */
public class TreeSelect implements Serializable public class TreeSelect implements Serializable
{ {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
/** 节点ID */ /** 节点ID */
private Long id; private Long id;
/** 节点名称 */ /** 节点名称 */
private String label; private String label;
/** 节点禁用 */ /** 节点禁用 */
private boolean disabled = false; private boolean disabled = false;
/** 子节点 */ /** 子节点 */
@JsonInclude(JsonInclude.Include.NON_EMPTY) @JsonInclude(JsonInclude.Include.NON_EMPTY)
private List<TreeSelect> children; private List<TreeSelect> children;
public TreeSelect() public TreeSelect()
{ {
} }
public TreeSelect(SysDept dept) public TreeSelect(SysDept dept)
{ {
this.id = dept.getDeptId(); this.id = dept.getDeptId();
this.label = dept.getDeptName(); this.label = dept.getDeptName();
this.disabled = StringUtils.equals(UserConstants.DEPT_DISABLE, dept.getStatus()); this.disabled = StringUtils.equals(UserConstants.DEPT_DISABLE, dept.getStatus());
this.children = dept.getChildren().stream().map(TreeSelect::new).collect(Collectors.toList()); this.children = dept.getChildren().stream().map(TreeSelect::new).collect(Collectors.toList());
} }
public TreeSelect(SysMenu menu) public TreeSelect(SysMenu menu)
{ {
this.id = menu.getMenuId(); this.id = menu.getMenuId();
this.label = menu.getMenuName(); this.label = menu.getMenuName();
this.children = menu.getChildren().stream().map(TreeSelect::new).collect(Collectors.toList()); this.children = menu.getChildren().stream().map(TreeSelect::new).collect(Collectors.toList());
} }
public Long getId() public Long getId()
{ {
return id; return id;
} }
public void setId(Long id) public void setId(Long id)
{ {
this.id = id; this.id = id;
} }
public String getLabel() public String getLabel()
{ {
return label; return label;
} }
public void setLabel(String label) public void setLabel(String label)
{ {
this.label = label; this.label = label;
} }
public boolean isDisabled() public boolean isDisabled()
{ {
return disabled; return disabled;
} }
public void setDisabled(boolean disabled) public void setDisabled(boolean disabled)
{ {
this.disabled = disabled; this.disabled = disabled;
} }
public List<TreeSelect> getChildren() public List<TreeSelect> getChildren()
{ {
return children; return children;
} }
public void setChildren(List<TreeSelect> children) public void setChildren(List<TreeSelect> children)
{ {
this.children = children; this.children = children;
} }
} }

View File

@@ -1,203 +1,203 @@
package com.ruoyi.common.core.domain.entity; package com.ruoyi.common.core.domain.entity;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import jakarta.validation.constraints.Email; import javax.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank; import javax.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
import jakarta.validation.constraints.Size; import javax.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;
/** /**
* 部门表 sys_dept * 部门表 sys_dept
* *
* @author ruoyi * @author ruoyi
*/ */
public class SysDept extends BaseEntity public class SysDept extends BaseEntity
{ {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
/** 部门ID */ /** 部门ID */
private Long deptId; private Long deptId;
/** 父部门ID */ /** 父部门ID */
private Long parentId; private Long parentId;
/** 祖级列表 */ /** 祖级列表 */
private String ancestors; private String ancestors;
/** 部门名称 */ /** 部门名称 */
private String deptName; private String deptName;
/** 显示顺序 */ /** 显示顺序 */
private Integer orderNum; private Integer orderNum;
/** 负责人 */ /** 负责人 */
private String leader; private String leader;
/** 联系电话 */ /** 联系电话 */
private String phone; private String phone;
/** 邮箱 */ /** 邮箱 */
private String email; private String email;
/** 部门状态:0正常,1停用 */ /** 部门状态:0正常,1停用 */
private String status; private String status;
/** 删除标志0代表存在 2代表删除 */ /** 删除标志0代表存在 2代表删除 */
private String delFlag; private String delFlag;
/** 父部门名称 */ /** 父部门名称 */
private String parentName; private String parentName;
/** 子部门 */ /** 子部门 */
private List<SysDept> children = new ArrayList<SysDept>(); private List<SysDept> children = new ArrayList<SysDept>();
public Long getDeptId() public Long getDeptId()
{ {
return deptId; return deptId;
} }
public void setDeptId(Long deptId) public void setDeptId(Long deptId)
{ {
this.deptId = deptId; this.deptId = deptId;
} }
public Long getParentId() public Long getParentId()
{ {
return parentId; return parentId;
} }
public void setParentId(Long parentId) public void setParentId(Long parentId)
{ {
this.parentId = parentId; this.parentId = parentId;
} }
public String getAncestors() public String getAncestors()
{ {
return ancestors; return ancestors;
} }
public void setAncestors(String ancestors) public void setAncestors(String ancestors)
{ {
this.ancestors = ancestors; this.ancestors = ancestors;
} }
@NotBlank(message = "部门名称不能为空") @NotBlank(message = "部门名称不能为空")
@Size(min = 0, max = 30, message = "部门名称长度不能超过30个字符") @Size(min = 0, max = 30, message = "部门名称长度不能超过30个字符")
public String getDeptName() public String getDeptName()
{ {
return deptName; return deptName;
} }
public void setDeptName(String deptName) public void setDeptName(String deptName)
{ {
this.deptName = deptName; this.deptName = deptName;
} }
@NotNull(message = "显示顺序不能为空") @NotNull(message = "显示顺序不能为空")
public Integer getOrderNum() public Integer getOrderNum()
{ {
return orderNum; return orderNum;
} }
public void setOrderNum(Integer orderNum) public void setOrderNum(Integer orderNum)
{ {
this.orderNum = orderNum; this.orderNum = orderNum;
} }
public String getLeader() public String getLeader()
{ {
return leader; return leader;
} }
public void setLeader(String leader) public void setLeader(String leader)
{ {
this.leader = leader; this.leader = leader;
} }
@Size(min = 0, max = 11, message = "联系电话长度不能超过11个字符") @Size(min = 0, max = 11, message = "联系电话长度不能超过11个字符")
public String getPhone() public String getPhone()
{ {
return phone; return phone;
} }
public void setPhone(String phone) public void setPhone(String phone)
{ {
this.phone = phone; this.phone = phone;
} }
@Email(message = "邮箱格式不正确") @Email(message = "邮箱格式不正确")
@Size(min = 0, max = 50, message = "邮箱长度不能超过50个字符") @Size(min = 0, max = 50, message = "邮箱长度不能超过50个字符")
public String getEmail() public String getEmail()
{ {
return email; return email;
} }
public void setEmail(String email) public void setEmail(String email)
{ {
this.email = email; this.email = email;
} }
public String getStatus() public String getStatus()
{ {
return status; return status;
} }
public void setStatus(String status) public void setStatus(String status)
{ {
this.status = status; this.status = status;
} }
public String getDelFlag() public String getDelFlag()
{ {
return delFlag; return delFlag;
} }
public void setDelFlag(String delFlag) public void setDelFlag(String delFlag)
{ {
this.delFlag = delFlag; this.delFlag = delFlag;
} }
public String getParentName() public String getParentName()
{ {
return parentName; return parentName;
} }
public void setParentName(String parentName) public void setParentName(String parentName)
{ {
this.parentName = parentName; this.parentName = parentName;
} }
public List<SysDept> getChildren() public List<SysDept> getChildren()
{ {
return children; return children;
} }
public void setChildren(List<SysDept> children) public void setChildren(List<SysDept> children)
{ {
this.children = children; this.children = children;
} }
@Override @Override
public String toString() { public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("deptId", getDeptId()) .append("deptId", getDeptId())
.append("parentId", getParentId()) .append("parentId", getParentId())
.append("ancestors", getAncestors()) .append("ancestors", getAncestors())
.append("deptName", getDeptName()) .append("deptName", getDeptName())
.append("orderNum", getOrderNum()) .append("orderNum", getOrderNum())
.append("leader", getLeader()) .append("leader", getLeader())
.append("phone", getPhone()) .append("phone", getPhone())
.append("email", getEmail()) .append("email", getEmail())
.append("status", getStatus()) .append("status", getStatus())
.append("delFlag", getDelFlag()) .append("delFlag", getDelFlag())
.append("createBy", getCreateBy()) .append("createBy", getCreateBy())
.append("createTime", getCreateTime()) .append("createTime", getCreateTime())
.append("updateBy", getUpdateBy()) .append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime()) .append("updateTime", getUpdateTime())
.toString(); .toString();
} }
} }

View File

@@ -1,176 +1,176 @@
package com.ruoyi.common.core.domain.entity; package com.ruoyi.common.core.domain.entity;
import jakarta.validation.constraints.NotBlank; import javax.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size; import javax.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;
import com.ruoyi.common.annotation.Excel.ColumnType; import com.ruoyi.common.annotation.Excel.ColumnType;
import com.ruoyi.common.constant.UserConstants; import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.domain.BaseEntity; import com.ruoyi.common.core.domain.BaseEntity;
/** /**
* 字典数据表 sys_dict_data * 字典数据表 sys_dict_data
* *
* @author ruoyi * @author ruoyi
*/ */
public class SysDictData extends BaseEntity public class SysDictData extends BaseEntity
{ {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
/** 字典编码 */ /** 字典编码 */
@Excel(name = "字典编码", cellType = ColumnType.NUMERIC) @Excel(name = "字典编码", cellType = ColumnType.NUMERIC)
private Long dictCode; private Long dictCode;
/** 字典排序 */ /** 字典排序 */
@Excel(name = "字典排序", cellType = ColumnType.NUMERIC) @Excel(name = "字典排序", cellType = ColumnType.NUMERIC)
private Long dictSort; private Long dictSort;
/** 字典标签 */ /** 字典标签 */
@Excel(name = "字典标签") @Excel(name = "字典标签")
private String dictLabel; private String dictLabel;
/** 字典键值 */ /** 字典键值 */
@Excel(name = "字典键值") @Excel(name = "字典键值")
private String dictValue; private String dictValue;
/** 字典类型 */ /** 字典类型 */
@Excel(name = "字典类型") @Excel(name = "字典类型")
private String dictType; private String dictType;
/** 样式属性(其他样式扩展) */ /** 样式属性(其他样式扩展) */
private String cssClass; private String cssClass;
/** 表格字典样式 */ /** 表格字典样式 */
private String listClass; private String listClass;
/** 是否默认Y是 N否 */ /** 是否默认Y是 N否 */
@Excel(name = "是否默认", readConverterExp = "Y=是,N=否") @Excel(name = "是否默认", readConverterExp = "Y=是,N=否")
private String isDefault; private String isDefault;
/** 状态0正常 1停用 */ /** 状态0正常 1停用 */
@Excel(name = "状态", readConverterExp = "0=正常,1=停用") @Excel(name = "状态", readConverterExp = "0=正常,1=停用")
private String status; private String status;
public Long getDictCode() public Long getDictCode()
{ {
return dictCode; return dictCode;
} }
public void setDictCode(Long dictCode) public void setDictCode(Long dictCode)
{ {
this.dictCode = dictCode; this.dictCode = dictCode;
} }
public Long getDictSort() public Long getDictSort()
{ {
return dictSort; return dictSort;
} }
public void setDictSort(Long dictSort) public void setDictSort(Long dictSort)
{ {
this.dictSort = dictSort; this.dictSort = dictSort;
} }
@NotBlank(message = "字典标签不能为空") @NotBlank(message = "字典标签不能为空")
@Size(min = 0, max = 100, message = "字典标签长度不能超过100个字符") @Size(min = 0, max = 100, message = "字典标签长度不能超过100个字符")
public String getDictLabel() public String getDictLabel()
{ {
return dictLabel; return dictLabel;
} }
public void setDictLabel(String dictLabel) public void setDictLabel(String dictLabel)
{ {
this.dictLabel = dictLabel; this.dictLabel = dictLabel;
} }
@NotBlank(message = "字典键值不能为空") @NotBlank(message = "字典键值不能为空")
@Size(min = 0, max = 100, message = "字典键值长度不能超过100个字符") @Size(min = 0, max = 100, message = "字典键值长度不能超过100个字符")
public String getDictValue() public String getDictValue()
{ {
return dictValue; return dictValue;
} }
public void setDictValue(String dictValue) public void setDictValue(String dictValue)
{ {
this.dictValue = dictValue; this.dictValue = dictValue;
} }
@NotBlank(message = "字典类型不能为空") @NotBlank(message = "字典类型不能为空")
@Size(min = 0, max = 100, message = "字典类型长度不能超过100个字符") @Size(min = 0, max = 100, message = "字典类型长度不能超过100个字符")
public String getDictType() public String getDictType()
{ {
return dictType; return dictType;
} }
public void setDictType(String dictType) public void setDictType(String dictType)
{ {
this.dictType = dictType; this.dictType = dictType;
} }
@Size(min = 0, max = 100, message = "样式属性长度不能超过100个字符") @Size(min = 0, max = 100, message = "样式属性长度不能超过100个字符")
public String getCssClass() public String getCssClass()
{ {
return cssClass; return cssClass;
} }
public void setCssClass(String cssClass) public void setCssClass(String cssClass)
{ {
this.cssClass = cssClass; this.cssClass = cssClass;
} }
public String getListClass() public String getListClass()
{ {
return listClass; return listClass;
} }
public void setListClass(String listClass) public void setListClass(String listClass)
{ {
this.listClass = listClass; this.listClass = listClass;
} }
public boolean getDefault() public boolean getDefault()
{ {
return UserConstants.YES.equals(this.isDefault); return UserConstants.YES.equals(this.isDefault);
} }
public String getIsDefault() public String getIsDefault()
{ {
return isDefault; return isDefault;
} }
public void setIsDefault(String isDefault) public void setIsDefault(String isDefault)
{ {
this.isDefault = isDefault; this.isDefault = isDefault;
} }
public String getStatus() public String getStatus()
{ {
return status; return status;
} }
public void setStatus(String status) public void setStatus(String status)
{ {
this.status = status; this.status = status;
} }
@Override @Override
public String toString() { public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("dictCode", getDictCode()) .append("dictCode", getDictCode())
.append("dictSort", getDictSort()) .append("dictSort", getDictSort())
.append("dictLabel", getDictLabel()) .append("dictLabel", getDictLabel())
.append("dictValue", getDictValue()) .append("dictValue", getDictValue())
.append("dictType", getDictType()) .append("dictType", getDictType())
.append("cssClass", getCssClass()) .append("cssClass", getCssClass())
.append("listClass", getListClass()) .append("listClass", getListClass())
.append("isDefault", getIsDefault()) .append("isDefault", getIsDefault())
.append("status", getStatus()) .append("status", getStatus())
.append("createBy", getCreateBy()) .append("createBy", getCreateBy())
.append("createTime", getCreateTime()) .append("createTime", getCreateTime())
.append("updateBy", getUpdateBy()) .append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime()) .append("updateTime", getUpdateTime())
.append("remark", getRemark()) .append("remark", getRemark())
.toString(); .toString();
} }
} }

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