128 Commits

Author SHA1 Message Date
267ff79b0c 😴发布 4.8.2 正式进入维护状态 2023-11-27 13:23:41 +08:00
a6f62ca86f 🎃 发布 4.8.1 稳定性增强 修复部分bug 2023-09-25 10:42:58 +08:00
8a692ed45a 🎃 发布 4.8.0 新增 sms4j 短信融合 2023-07-10 11:06:58 +08:00
6f6ac2c0cf ⚔ 发布 4.7.0 稳定性版本 2023-05-08 09:54:23 +08:00
36ac478624 🎇发布 4.6.0 新增 数据库加解密 与 通用翻译 功能 2023-03-13 10:10:47 +08:00
f196010416 fix 修复 新版本 Redisson 存在与 boot 2.X 的兼容性问题 2023-01-12 15:17:16 +08:00
173862360e 🧧发布 4.5.0 新春版 2023-01-12 09:55:50 +08:00
34574c5bf7 发布 4.4.0 正式版 2022-11-28 14:42:17 +08:00
02e9ac799d 🐬发布 4.3.1 修复了一些问题建议升级 2022-10-24 14:36:47 +08:00
0f237ef7ed fix 修复 日志转换非json数据导致报错 2022-09-13 18:28:55 +08:00
817da4d2b8 fix 修复 用户导入存在则更新不生效 2022-09-13 18:28:44 +08:00
ee48cd7d01 🐣发布 4.3.0 正式版 2022-09-13 16:31:26 +08:00
c5f4dec559 发布 v4.2.0 2022-06-28 22:51:57 +08:00
e0527b3350 Merge remote-tracking branch 'origin/fast' into fast 2022-04-24 14:09:28 +08:00
d5520817bd 发布 4.1.0 2022-04-24 14:09:19 +08:00
7c04240317 fix 修复 数据权限 从 aop 切换到 拦截器 导致获取代理失败问题 2022-03-28 21:03:52 +08:00
2cf283b8c6 发布 4.0.1 2022-03-01 10:37:26 +08:00
0e81a7c342 fix 修复 minio 适配 https 导致的问题 2022-02-18 14:08:21 +08:00
6fa53ebe31 fix 修复 minio 适配 https 导致的问题 2022-02-18 14:08:01 +08:00
356f7ec184 Merge remote-tracking branch 'origin/fast' into fast 2022-02-18 11:38:12 +08:00
400ecdf0ab 发布 4.0.0 2022-02-18 11:37:21 +08:00
28916bd384 fix 修复 数据权限 缓存方法名错误问题 2022-01-26 10:33:49 +00:00
dafb7477f6 update 注释遗漏 老版本数据权限 2021-12-28 14:30:31 +08:00
55e3e93199 发布 v3.5.0-release 正式版 2021-12-28 11:00:10 +08:00
5857db7c5a fix 修复代码生成 导出注解错误 2021-12-13 10:04:33 +08:00
5674d4a618 update 更改前端工程文件版本号
(cherry picked from commit 255b5f2f07)
2021-11-30 11:12:47 +08:00
fd45cdb882 update 补全漏提交文件 2021-11-29 22:07:22 +08:00
c76ab64e8a 发布 v3.4.0 2021-11-29 14:26:23 +08:00
d81377a2ed fix 由于 fast 单体版 代码统一管理 无法排除 quartz 导致运行异常 故优先删除 quartz 相关代码 2021-11-07 20:28:01 +08:00
23cb4eef33 fix 修复通用实体 传参无法接收问题 2021-11-02 22:46:05 +08:00
45e2672e26 fix 修复 xxl-job-admin 部署问题 2021-11-01 13:50:22 +08:00
b98112fd92 fix 修复 SysOss、SysOssConfig 未继承 BaseEntity 基础实体问题 2021-10-31 21:33:54 +08:00
4d12424378 发布 v3.3.0 2021-10-29 09:18:18 +08:00
6def4aa84d fix 修复 多数据源aop语法错误 2021-09-28 14:40:03 +08:00
9351cc4426 发布 v3.2.0 2021-09-28 10:09:53 +08:00
242a74a8ae update 移除无用依赖 2021-09-26 18:04:40 +08:00
ad566e9283 update 回滚 配置检测拦截是否有效SQL 因不通用 2021-09-09 17:41:04 +08:00
5a0136a655 发布 v3.1.0 2021-09-07 14:25:55 +08:00
33033d7d78 !85 fix OssFactory编译报错
Merge pull request !85 from dawn9117/N/A
2021-09-02 08:27:51 +00:00
57ff78d7aa fix OssFactory编译报错 2021-09-02 08:26:17 +00:00
849a131982 !81 fast版 oss上传出错
Merge pull request !81 from 李魁哲/lkz
2021-08-21 02:28:59 +00:00
a66bd96a31 !3 oss上传文件报错
Merge pull request !3 from 李魁哲/N/A
2021-08-21 01:55:23 +00:00
44dfbd24a8 oss上传文件报错 2021-08-21 01:54:56 +00:00
de658c307d !2 21231
Merge pull request !2 from 李魁哲/fast
2021-08-20 10:00:22 +00:00
01f3a94406 Merge branch 'lkz' of gitee.com:lkz9773/RuoYi-Vue-Plus into fast 2021-08-20 10:00:03 +00:00
20d6a893cb fix 修复 excel 导入与 class 未对应问题 2021-08-20 17:02:18 +08:00
4e6057d01e !1 3.00
* update 优化 OSS 模块与上传组件 异常处理
* fix 修复 OSS配置清空被过滤问题
* fix 修复 新版本说明 标签错误
* fix 修复 富文本图片路径错误问题
* fix 修复 minio 无 perfix 问题
* 发布 v3.0.0
* update 降级 minio 依赖版本
* update service 统一使用 ServicePlusImpl
2021-08-20 08:52:13 +00:00
879f18f6f0 update 优化 OSS 模块与上传组件 异常处理 2021-08-18 19:19:12 +08:00
12e69e946e fix 修复 OSS配置清空被过滤问题 2021-08-18 18:25:17 +08:00
d4758aae1e fix 修复 新版本说明 标签错误
(cherry picked from commit 96c4c4da56)
2021-08-18 16:56:04 +08:00
05ca59a525 fix 修复 富文本图片路径错误问题
(cherry picked from commit cf4b49ca3b)
2021-08-18 14:50:31 +08:00
ba018d0d6c fix 修复 minio 无 perfix 问题 2021-08-18 14:15:55 +08:00
c206f938ba 发布 v3.0.0 2021-08-18 11:45:51 +08:00
3294390407 update 降级 minio 依赖版本
(cherry picked from commit a6bde3c5da)
2021-07-30 14:18:13 +08:00
39e3152ed0 update service 统一使用 ServicePlusImpl 2021-07-28 14:43:21 +08:00
2b3ac89fa1 fix 修复 jdk8 与 jdk11 差异问题 2021-07-28 11:57:34 +08:00
3f3a7db544 发布 v2.6.0 2021-07-28 11:32:30 +08:00
a3e781915e fix 修复多数据源druid全局配置缩进错误 引起无效配置问题 2021-07-24 18:24:29 +08:00
dc5c5c292e remove 移除无用配置
(cherry picked from commit aad482a7e0)
2021-07-20 11:15:33 +08:00
fc1864c52e remove 删除无用文档与脚本
(cherry picked from commit 50b7421f28)
2021-07-20 11:14:56 +08:00
8e8520060d 发布 v2.5.2 2021-07-20 11:03:57 +08:00
51d1e3c8c1 发布 v2.5.1 针对 v2.5.0 版本新特性bug修复 2021-07-13 13:57:44 +08:00
49c2809895 Merge remote-tracking branch 'origin/fast' into fast 2021-07-12 11:36:47 +08:00
007a6d0c88 发布 v2.5.0 2021-07-12 11:36:37 +08:00
a77ee34a73 update README.md. 2021-06-25 08:01:35 +00:00
7e3bbb4aab update 更新文档 提问四部曲 2021-06-24 17:13:39 +08:00
17ed4adb90 update 更新文档 提问四部曲 2021-06-24 17:11:14 +08:00
4e93575c94 update 修改readme加入提问四部曲 2021-06-24 17:11:13 +08:00
0e67a487c3 fix 相对路径下载问题 2021-06-24 15:43:46 +08:00
31e4735dcb 发布 v2.4.0 2021-06-24 09:52:40 +08:00
03c459e5a3 同步 dev 分支 2021-06-23 10:02:55 +08:00
3e5b850e25 发布 v2.3.2 2021-06-11 10:00:05 +08:00
801f7cd8f7 发布 2.3.1 2021-06-04 16:20:12 +08:00
d87eb34352 Merge remote-tracking branch 'origin/fast' into fast 2021-06-01 10:53:36 +08:00
59ef30b156 发布 2.3.0 2021-06-01 10:53:30 +08:00
47e2a3e116 fix 修复数据权限编写错误 2021-05-29 21:49:35 +08:00
76aa006db5 update 还原数据权限修改 2021-05-29 19:49:22 +08:00
fab58a4f77 发布 2.2.1 2021-05-29 19:23:45 +08:00
96cdd2490d 同步dev分支 2021-05-26 16:52:24 +08:00
a90a5e9cd9 Merge remote-tracking branch 'origin/fast' into fast
# Conflicts:
#	README.md
2021-05-26 16:51:22 +08:00
08b339b25e 同步dev分支 2021-05-26 16:51:01 +08:00
002c7ffca5 update 更新捐献二维码 2021-05-25 20:45:56 +08:00
a42ef126cd 版本更新 v2.2.0 2021-05-25 14:31:52 +08:00
8a94526110 发版 2.1.2 2021-05-21 18:00:40 +08:00
33c6fdfaa9 发布 v2.1.1 2021-05-18 11:50:29 +08:00
403c12eb9c 版本更新 v2.1.0 2021-05-15 14:45:47 +08:00
687d746b1b 正式发布 v2.0.0 2021-05-14 21:39:30 +08:00
b608002e89 版本更新 v1.0.2 2021-05-13 09:25:56 +08:00
fe8a2b401c 版本更新 v1.0.1 2021-05-11 17:46:48 +08:00
4a4d8f7123 正式发布 1.0.0 2021-05-10 15:32:46 +08:00
92008ff2d7 update 更新作者二维码 2021-05-08 23:56:36 +08:00
3fbf0a8e9e Merge remote-tracking branch 'origin/fast' into fast 2021-05-08 23:37:35 +08:00
0cbcc56cd6 fix 修复数据权限问题 2021-05-08 23:36:50 +08:00
ea7b309211 fix 日志时间sql符号转换问题 2021-05-08 17:07:41 +08:00
d945cb4a30 fix 日志时间sql符号转换问题 2021-05-08 16:56:52 +08:00
ab3e04f3ad update 项目地址项目名 2021-05-06 17:45:27 +08:00
2b5f30b88b fix 部门权限问题 2021-04-28 15:59:04 +08:00
9cb68a350b fix 日志时间问题 2021-04-28 11:52:38 +08:00
14a9df8b7e update 修改MP验证策略 NOT_NULL -> NOT_EMPTY 2021-04-25 10:40:32 +08:00
661325e4c5 同步ruoyi 2021-04-25 09:46:49 +08:00
017faa99c2 update 重写MP注入器 2021-04-25 09:20:39 +08:00
dbe6494b6c update 屏蔽用户密码返回 2021-04-23 16:01:32 +08:00
789dab5138 update 补全实体类 注入注解 2021-04-22 21:11:04 +08:00
e48d5fadc5 add 集成 spring-boot-admin 全方位监控 2021-04-22 15:50:42 +08:00
70492a9715 update mp 化 2021-04-22 10:11:39 +08:00
a3ee939ebb fix feign熔断问题 2021-04-22 09:33:36 +08:00
bd07a69712 fix 代码生成器编辑问题 2021-04-19 19:01:03 +08:00
58d08f0ecf fix Feign 熔断不生效 bug 2021-04-19 17:52:00 +08:00
af07590fd3 Merge branch 'master' of https://gitee.com/y_project/RuoYi-Vue into fast
 Conflicts:
	pom.xml
	ruoyi-ui/src/assets/styles/ruoyi.scss
	ruoyi-ui/src/components/ThemePicker/index.vue
	ruoyi-ui/src/layout/components/Settings/index.vue
	ruoyi-ui/src/store/modules/settings.js
	ruoyi/src/main/java/com/ruoyi/framework/aspectj/LogAspect.java
	ruoyi/src/main/java/com/ruoyi/generator/util/VelocityInitializer.java
2021-04-19 17:48:30 +08:00
b36b9ac788 Merge branch 'master' of https://gitee.com/y_project/RuoYi-Vue into fast
 Conflicts:
	ruoyi/src/main/resources/vm/vue/index-tree.vue.vm
2021-04-16 11:34:02 +08:00
76d49217bb fix 表名上传错误 2021-04-16 11:31:36 +08:00
5b06ff45c5 update 导出 Excel 工作表的名称修改 2021-04-14 14:37:27 +08:00
d4fdcb0894 update 完成所有原生功能使用 Mybatis-Plus 与 Lombok 重写 2021-04-14 13:46:41 +08:00
f28029fade Merge branch 'master' of https://gitee.com/y_project/RuoYi-Vue into fast
 Conflicts:
	ruoyi-generator/src/main/resources/vm/java/controller.java.vm
	ruoyi-generator/src/main/resources/vm/xml/mapper.xml.vm
	ruoyi-ui/src/assets/styles/ruoyi.scss
	ruoyi-ui/src/assets/styles/sidebar.scss
	ruoyi-ui/src/layout/components/Navbar.vue
	ruoyi-ui/src/layout/components/Settings/index.vue
	ruoyi-ui/src/layout/components/TagsView/index.vue
	ruoyi-ui/src/settings.js
	ruoyi-ui/src/store/getters.js
	ruoyi-ui/src/store/modules/permission.js
	ruoyi-ui/src/store/modules/settings.js
	ruoyi-ui/src/store/modules/tagsView.js
	ruoyi-ui/src/views/monitor/druid/index.vue
	ruoyi/src/main/resources/application-prod.yml
2021-04-14 13:33:01 +08:00
6aa03ce709 fix bo缺包问题 2021-04-12 10:38:34 +08:00
89f30d9235 update Date参数接收Bo实体格式转换 2021-04-09 11:50:44 +08:00
e8bb56938e Merge branch 'master' of https://gitee.com/y_project/RuoYi-Vue into fast
 Conflicts:
	ruoyi-ui/src/assets/styles/ruoyi.scss
	ruoyi-ui/src/utils/zipdownload.js
	ruoyi/src/main/java/com/ruoyi/framework/interceptor/impl/SameUrlDataInterceptor.java
	ruoyi/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java
	ruoyi/src/main/resources/mapper/system/SysRoleMapper.xml
	ruoyi/src/main/resources/mapper/system/SysUserMapper.xml
2021-04-08 17:19:25 +08:00
43d7949246 fix 字节转换 bug 2021-04-08 16:42:03 +08:00
307c4984a9 update 默认增加editBo主键生成 2021-04-08 16:30:28 +08:00
fb6290e481 fix controller 接口路径问题 2021-04-04 20:02:42 +08:00
24be6a0b7a fix 代码生成器问题 2021-04-04 11:29:40 +08:00
bbc8a2c062 fix 父类少包问题 2021-04-04 11:29:20 +08:00
aaa6b7ed3c fix remove 方法类型错误 2021-04-03 17:01:23 +08:00
a4448fef0a fix Page 路径导入 2021-04-02 23:07:57 +08:00
4ef331cf80 add 添加多模块分支 2021-04-02 16:15:29 +08:00
b8806360f8 add 添加单模块分支 2021-04-02 16:13:31 +08:00
fad9a8a168 add 添加单模块分支 2021-04-02 16:12:58 +08:00
2ba304819d init 单模块项目 2021-04-02 15:59:05 +08:00
817 changed files with 27999 additions and 6556 deletions

View File

@ -1,13 +1,49 @@
### 使用版本(未按照模板填写直接删除)
- jdk版本(带上尾号): 例如 1.8.0_202
- 框架版本(项目启动时输出的版本号): 例如 4.4.0
- 其他依赖版本(你觉得有必要的):
### 问题前提
> 功能不好用 不会用 是否已经看过项目文档
> 项目运行报错 是否已经拿着报错信息去百度 常见报错百度百度足以
> 是否搜索过其他issue 一些已经解决的问题 会在issue内留下解决方法
> 无法线上解决或者与框架无关的问题的欢迎加VIP群跟作者一对一谈
### 异常模块
> 此报错都涉及到那些系统模块
例如 ruoyi-system ruoyi-auth 等等
### 问题描述
> 越详细越容易直击问题所在
已知: XXX功能不好用 或 XXX数据不正常 等等
### 希望结果
> 想知道你觉得怎么样是正常或者合理的
希望功能可以有XXX结果 或者 XXX现象
### 重现步骤
> 作者并不知道这个问题是如何出现的
### 报错信息(截图为主 请勿发混乱格式)
- 1
- 2
- 3
### 相关代码与报错信息(请勿发混乱格式)
> 代码可按照如下形式提供或者截图均可 越详细越好
> 大多数问题都是 代码编写错误问题 逻辑问题 或者用法错误等问题
```java
public class XXX {
}
```

View File

@ -0,0 +1,50 @@
name: Bug 反馈
description: 当你中发现了一个 Bug导致应用崩溃或抛出异常或者有一个组件存在问题或者某些地方看起来不对劲。
title: "[Bug]: "
labels: ["bug"]
body:
- type: textarea
id: version
attributes:
label: 版本
description: 你当前正在使用我们软件的哪个版本(pom文件内的版本号)
value: |
jdk版本(带上尾号): 例如 1.8.0
框架版本(项目启动时输出的版本号): 例如 4.4.0
其他依赖版本(你觉得有必要的):
validations:
required: true
- type: checkboxes
attributes:
label: 功能不好用不会用是否已经看过项目文档?
options:
- label: https://plus-doc.dromara.org
required: true
- type: checkboxes
attributes:
label: 这个问题是否已经存在?
options:
- label: 我已经搜索过现有的问题 (https://gitee.com/dromara/RuoYi-Vue-Plus/issues)
required: true
- type: textarea
attributes:
label: 希望结果
description: 想知道你觉得怎么样是正常或者合理的。
validations:
required: true
- type: markdown
attributes:
label: 如何复现
description: 请详细告诉我们如何复现你遇到的问题
value: |
如涉及代码 可提供一个最小代码示例 并使用```附上它 或者截图均可 越详细越好<br>
大多数问题都是 代码编写错误问题 逻辑问题 或者用法错误等问题
validations:
required: true
- type: textarea
attributes:
label: 相关代码与报错信息(请勿发混乱格式)
description: 如果可以的话,上传任何关于 bug 的截图。
value: |
[在这里上传图片]

View File

@ -0,0 +1,5 @@
blank_issues_enabled: false
contact_links:
- name: RuoYi-Vue-Plus 文档中心
url: https://plus-doc.dromara.org
about: 提供 RuoYi-Vue-Plus 搭建使用指南、平台基本开发使用方式、介绍、基础知识和常见问题解答

View File

@ -0,0 +1,43 @@
name: 功能建议
description: 对本项目提出一个功能建议
title: "[功能建议]: "
labels: ["enhancement"]
body:
- type: markdown
attributes:
value: |
感谢提出功能建议我们将仔细考虑请持续关注该issues在加入计划后我们会有贡献者设置为负责人同时状态成为进行中。
- type: textarea
id: related-problem
attributes:
label: 你的功能建议是否和某个问题相关?
description: 清晰并简洁地描述问题是什么,例如,当我...时,我总是感到困扰。
validations:
required: false
- type: textarea
id: desired-solution
attributes:
label: 你希望看到什么解决方案?
description: 清晰并简洁地描述你希望发生的事情。
validations:
required: true
- type: textarea
id: alternatives
attributes:
label: 你考虑过哪些替代方案?
description: 清晰并简洁地描述你考虑过的任何替代解决方案或功能。
validations:
required: false
- type: textarea
id: additional-context
attributes:
label: 你有其他上下文或截图吗?
description: 在此处添加有关功能请求的任何其他上下文或截图。
validations:
required: false
- type: checkboxes
attributes:
label: 意向参与贡献
options:
- label: 我有意向参与具体功能的开发实现并将代码贡献回到上游社区
required: false

View File

@ -1,7 +1,7 @@
### 更改目的 解决了什么问题(请提交到dev分支)
### 描述 做了哪些改动
### 改动逻辑 这么写的思路(让作者更好的理解你的意图)
### 测试 都做了哪些测试(未经过测试不采纳)

View File

@ -2,7 +2,7 @@
<configuration default="false" name="ruoyi-monitor-admin" type="docker-deploy" factoryName="dockerfile" server-name="Docker">
<deployment type="dockerfile">
<settings>
<option name="imageTag" value="ruoyi/ruoyi-monitor-admin:4.3.0" />
<option name="imageTag" value="ruoyi/ruoyi-monitor-admin:4.8.2" />
<option name="buildOnly" value="true" />
<option name="sourceFilePath" value="ruoyi-extend/ruoyi-monitor-admin/Dockerfile" />
</settings>

View File

@ -2,7 +2,7 @@
<configuration default="false" name="ruoyi-server" type="docker-deploy" factoryName="dockerfile" server-name="Docker">
<deployment type="dockerfile">
<settings>
<option name="imageTag" value="ruoyi/ruoyi-server:4.3.0" />
<option name="imageTag" value="ruoyi/ruoyi-server:4.8.2" />
<option name="buildOnly" value="true" />
<option name="sourceFilePath" value="ruoyi-admin/Dockerfile" />
</settings>

View File

@ -2,7 +2,7 @@
<configuration default="false" name="ruoyi-xxl-job-admin" type="docker-deploy" factoryName="dockerfile" server-name="Docker">
<deployment type="dockerfile">
<settings>
<option name="imageTag" value="ruoyi/ruoyi-xxl-job-admin:4.3.0" />
<option name="imageTag" value="ruoyi/ruoyi-xxl-job-admin:4.8.2" />
<option name="buildOnly" value="true" />
<option name="sourceFilePath" value="ruoyi-extend/ruoyi-xxl-job-admin/Dockerfile" />
</settings>

244
README.md
View File

@ -1,10 +1,24 @@
<img src="https://foruda.gitee.com/images/1679673773341074847/178e8451_1766278.png" width="50%" height="50%">
<div style="height: 10px; clear: both;"></div>
- - -
## 版本状态说明
由于 springboot 2.X 与 vue 2.X 官方均宣布停止维护, 故而 框架 4.X 版本 进入维护状态(只处理问题不更新功能)
停止维护时间预计: 2024年6-10月具体根据使用人数动态决定, 此版本已经相当稳定 即便不更新功能也不影响使用
如果依旧选择使用 jdk8 或者 jdk11 可以放心使用此版本, 如果希望使用 jdk17 或者 jdk21 可以选择使用 5.X 分支
## 平台简介
[![码云Gitee](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/badge/star.svg?theme=blue)](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus)
[![GitHub](https://img.shields.io/github/stars/JavaLionLi/RuoYi-Vue-Plus.svg?style=social&label=Stars)](https://github.com/JavaLionLi/RuoYi-Vue-Plus)
[![License](https://img.shields.io/badge/License-MIT-blue.svg)](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/blob/master/LICENSE)
[![码云Gitee](https://gitee.com/dromara/RuoYi-Vue-Plus/badge/star.svg?theme=blue)](https://gitee.com/dromara/RuoYi-Vue-Plus)
[![GitHub](https://img.shields.io/github/stars/JavaLionLi/RuoYi-Vue-Plus.svg?style=social&label=Stars)](https://github.com/dromara/RuoYi-Vue-Plus)
[![License](https://img.shields.io/badge/License-MIT-blue.svg)](https://gitee.com/dromara/RuoYi-Vue-Plus/blob/master/LICENSE)
[![使用IntelliJ IDEA开发维护](https://img.shields.io/badge/IntelliJ%20IDEA-提供支持-blue.svg)](https://www.jetbrains.com/?from=RuoYi-Vue-Plus)
<br>
[![RuoYi-Vue-Plus](https://img.shields.io/badge/RuoYi_Vue_Plus-4.3.0-success.svg)](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus)
[![RuoYi-Vue-Plus](https://img.shields.io/badge/RuoYi_Vue_Plus-4.8.2-success.svg)](https://gitee.com/dromara/RuoYi-Vue-Plus)
[![Spring Boot](https://img.shields.io/badge/Spring%20Boot-2.7-blue.svg)]()
[![JDK-8+](https://img.shields.io/badge/JDK-8-green.svg)]()
[![JDK-11](https://img.shields.io/badge/JDK-11-green.svg)]()
@ -14,62 +28,95 @@
> 项目代码、文档 均开源免费可商用 遵循开源协议在项目中保留开源协议文件即可<br>
活到老写到老 为兴趣而开源 为学习而开源 为让大家真正可以学到技术而开源
> 系统演示: [传送门](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/系统演示?sort_id=4836388)
> 系统演示: [传送门](https://gitee.com/dromara/RuoYi-Vue-Plus/wikis/pages?sort_id=4836388&doc_id=1469725)
| 功能介绍 | 使用技术 | 文档地址 | 特性注意事项 |
|----------|---------------------|---------------------------------------------------------------------------------------------------|----------------------------|
| 当前框架 | RuoYi-Vue-Plus | [RuoYi-Vue-Plus文档](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/pages) | 重写RuoYi-Vue全方位升级(不兼容原框架) |
| 微服务分支 | RuoYi-Cloud-Plus | [微服务分支地址](https://gitee.com/JavaLionLi/RuoYi-Cloud-Plus) | 重写RuoYi-Cloud全方位升级(不兼容原框架) |
| 单体分支 | RuoYi-Vue-Plus-fast | [fast分支地址](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/tree/fast/) | 单体应用结构 |
| Vue3分支 | RuoYi-Vue-Plus-UI | [UI地址](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus-UI) | 由于组件还未完善 仅供学习 |
| 原框架 | RuoYi-Vue | [RuoYi-Vue官网](http://ruoyi.vip/) | 定期同步需要的功能 |
| 前端开发框架 | Vue、Element UI | [Element UI官网](https://element.eleme.cn/#/zh-CN) | |
| 后端开发框架 | SpringBoot | [SpringBoot官网](https://spring.io/projects/spring-boot/#learn) | |
| 容器框架 | Undertow | [Undertow官网](https://undertow.io/) | 基于 XNIO 的高性能容器 |
| 权限认证框架 | Sa-Token、Jwt | [Sa-Token官网](https://sa-token.dev33.cn/) | 强解耦、强扩展 |
| 关系数据库 | MySQL | [MySQL官网](https://dev.mysql.com/) | 适配 8.X 最低 5.7 |
| 关系数据库 | Oracle | [Oracle官网](https://www.oracle.com/cn/database/) | 适配 11g 12c |
| 关系数据库 | PostgreSQL | [PostgreSQL官网](https://www.postgresql.org/) | 适配 13 14 |
| 关系数据库 | SQLServer | [SQLServer官网](https://docs.microsoft.com/zh-cn/sql/sql-server) | 适配 2017 2019 |
| 缓存数据库 | Redis | [Redis官网](https://redis.io/) | 适配 6.X 最低 4.X |
| 数据库框架 | Mybatis-Plus | [Mybatis-Plus文档](https://baomidou.com/guide/) | 快速 CRUD 增加开发效率 |
| 数据库框架 | p6spy | [p6spy官网](https://p6spy.readthedocs.io/) | 更强劲的 SQL 分析 |
| 数据源框架 | dynamic-datasource | [dynamic-ds文档](https://www.kancloud.cn/tracy5546/dynamic-datasource/content) | 支持主从与多种类数据库异构 |
| 序列化框架 | Jackson | [Jackson官网](https://github.com/FasterXML/jackson) | 统一使用 jackson 高效可靠 |
| Redis客户端 | Redisson | [Redisson文档](https://github.com/redisson/redisson/wiki/%E7%9B%AE%E5%BD%95) | 支持单机、集群配置 |
| 分布式限流 | Redisson | [Redisson文档](https://github.com/redisson/redisson/wiki/%E7%9B%AE%E5%BD%95) | 全局、请求IP、集群ID 多种限流 |
| 分布式队列 | Redisson | [Redisson文档](https://github.com/redisson/redisson/wiki/%E7%9B%AE%E5%BD%95) | 普通队列、延迟队列、优先队列 等 |
| 分布式锁 | Lock4j | [Lock4j官网](https://gitee.com/baomidou/lock4j) | 注解锁、工具锁 多种多样 |
| 分布式幂等 | Redisson | [Lock4j文档](https://gitee.com/baomidou/lock4j) | 拦截重复提交 |
| 分布式日志 | TLog | [TLog文档](https://yomahub.com/tlog/docs) | 支持跟踪链路日志记录、性能分析、链路排查 |
| 分布式任务调度 | Xxl-Job | [Xxl-Job官网](https://www.xuxueli.com/xxl-job/) | 高性能 高可靠 易扩展 |
| 文件存储 | Minio | [Minio文档](https://docs.min.io/) | 本地存储 |
| 文件存储 | 七牛、阿里、腾讯 | [OSS使用文档](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/pages?sort_id=4359146&doc_id=1469725) | 云存储 |
| 短信模块 | 阿里、腾讯 | [短信使用文档](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/pages?sort_id=5578491&doc_id=1469725) | 短信发送 |
| 监控框架 | SpringBoot-Admin | [SpringBoot-Admin文档](https://codecentric.github.io/spring-boot-admin/current/) | 全方位服务监控 |
| 校验框架 | Validation | [Validation文档](https://docs.jboss.org/hibernate/stable/validator/reference/en-US/html_single/) | 增强接口安全性、严谨性 支持国际化 |
| Excel框架 | Alibaba EasyExcel | [EasyExcel文档](https://www.yuque.com/easyexcel/doc/easyexcel) | 性能优异 扩展性强 |
| 文档框架 | SpringDoc、javadoc | [接口文档](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/pages?sort_id=5805266&doc_id=1469725) | 无注解零入侵基于java注释 |
| 工具类框架 | Hutool、Lombok | [Hutool文档](https://www.hutool.cn/docs/) | 减少代码冗余 增加安全性 |
| 代码生成器 | 适配MP、Knife4j规范化代码 | [Hutool文档](https://www.hutool.cn/docs/) | 一键生成前后端代码 |
| 部署方式 | Docker | [Docker文档](https://docs.docker.com/) | 容器编排 一键部署业务集群 |
| 国际化 | SpringMessage | [SpringMVC文档](https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#mvc) | Spring标准国际化方案 |
# 本框架与RuoYi的功能差异
| 功能 | 本框架 | RuoYi |
|-------------|-------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------|
| 前端项目 | 基于vue3-element-admin开源项目重写<br/>Vue3 + TS + ElementPlus | 基于Vue2/Vue3 + JS |
| 后端项目结构 | 采用插件化 + 扩展包形式 结构解耦 易于扩展 | 模块相互注入耦合严重难以扩展 |
| 后端代码风格 | 严格遵守Alibaba规范与项目统一配置的代码格式化 | 代码书写与常规结构不同阅读障碍大 |
| Web容器 | 采用 Undertow 基于 XNIO 的高性能容器 | 采用 Tomcat |
| 权限认证 | 采用 Sa-Token、Jwt 静态使用功能齐全 低耦合 高扩展 | Spring Security 配置繁琐扩展性极差 |
| 权限注解 | 采用 Sa-Token 支持注解 登录校验、角色校验、权限校验、二级认证校验、HttpBasic校验、忽略校验<br/>角色与权限校验支持多种条件 如 `AND` `OR``权限 OR 角色` 等复杂表达式 | 只支持是否存在匹配 |
| 关系数据库支持 | 原生支持 MySQL、Oracle、PostgreSQL、SQLServer<br/>可同时使用异构切换 | 支持 Mysql、Oracle 不支持同时使用、不支持异构切换 |
| 缓存数据库 | 支持 Redis 5-7 支持大部分新功能特性 如 分布式限流、分布式队列 | Redis 简单 get set 支持 |
| Redis客户端 | 采用 Redisson Redis官方推荐 基于Netty的客户端工具<br/>支持Redis 90%以上的命令 底层优化规避很多不正确的用法 例如: keys被转换为scan<br/>支持单机、哨兵、单主集群、多主集群等模式 | Lettuce + RedisTemplate 支持模式少 工具使用繁琐<br/>连接池采用 common-pool Bug多经常性出问题 |
| 缓存注解 | 采用 Spring-Cache 注解 对其扩展了实现支持了更多功能<br/>例如 过期时间 最大空闲时间 组最大长度等 只需一个注解即可完成数据自动缓存 | 需手动编写Redis代码逻辑 |
| ORM框架 | 采用 Mybatis-Plus 基于对象几乎不用写SQL全java操作 功能强大插件众多<br/>例如多租户插件 分页插件 乐观锁插件等等 | 采用 Mybatis 基于XML需要手写SQL |
| SQL监控 | 采用 p6spy 可输出完整SQL与执行时间监控 | log输出 需手动拼接sql与参数无法快速查看调试问题 |
| 数据分页 | 采用 Mybatis-Plus 分页插件<br/>框架对其进行了扩展 对象化分页对象 支持多种方式传参 支持前端多排序 复杂排序 | 采用 PageHelper 仅支持单查询分页 参数只能从param传 只能单排序 功能扩展性差 体验不好 |
| 数据权限 | 采用 Mybatis-Plus 插件 自行分析拼接SQL 无感式过滤<br/>只需为Mapper设置好注解条件 支持多种自定义 不限于部门角色 | 采用 注解+aop 实现 基于部门角色 生成的sql兼容性差 不支持其他业务扩展<br/>生成sql后需手动拼接到具体业务sql上 对于多个Mapper查询不起作用 |
| 数据脱敏 | 采用 注解 + jackson 序列化期间脱敏 支持不同模块不同的脱敏条件<br/>支持多种策略 如身份证、手机号、地址、邮箱、银行卡等 可自行扩展 | 无 |
| 数据加解密 | 采用 注解 + mybatis 拦截器 对存取数据期间自动加解密<br/>支持多种策略 如BASE64、AES、RSA、SM2、SM4等 | 无 |
| 数据翻译 | 采用 注解 + jackson 序列化期间动态修改数据 数据进行翻译<br/>支持多种模式: `映射翻译` `直接翻译` `其他扩展条件翻译` 接口化两步即可完成自定义扩展 内置多种翻译实现 | 无 |
| 多数据源框架 | 采用 dynamic-datasource 支持世面大部分数据库<br/>通过yml配置即可动态管理异构不同种类的数据库 也可通过前端页面添加数据源<br/>支持spel表达式从请求头参数等条件切换数据源 | 基于 druid 手动编写代码配置数据源 配置繁琐 支持性差 |
| 多数据源事务 | 采用 dynamic-datasource 支持多数据源不同种类的数据库事务回滚 | 不支持 |
| 数据库连接池 | 采用 HikariCP Spring官方内置连接池 配置简单 以性能与稳定性闻名天下 | 采用 druid bug众多 社区维护差 活跃度低 配置众多繁琐性能一般 |
| 数据库主键 | 采用 雪花ID 基于时间戳的 有序增长 唯一ID 再也不用为分库分表 数据合并主键冲突重复而发愁 | 采用 数据库自增ID 支持数据量有限 不支持多数据源主键唯一 |
| WebSocket协议 | 基于 Spring 封装的 WebSocket 协议 扩展了Token鉴权与分布式会话同步 不再只是基于单机的废物 | 无 |
| 序列化 | 采用 Jackson Spring官方内置序列化 靠谱!!! | 采用 fastjson bugjson 远近闻名 |
| 分布式幂等 | 参考美团GTIS防重系统简化实现(细节可看文档) | 手动编写注解基于aop实现 |
| 分布式任务调度 | 采用 Xxl-Job 天生支持分布式 统一的管理中心 | 采用 Quartz 基于数据库锁性能差 集群需要做很多配置与改造 |
| 文件存储 | 采用 Minio 分布式文件存储 天生支持多机、多硬盘、多分片、多副本存储<br/>支持权限管理 安全可靠 文件可加密存储 | 采用 本机文件存储 文件裸漏 易丢失泄漏 不支持集群有单点效应 |
| 云存储 | 采用 AWS S3 协议客户端 支持 七牛、阿里、腾讯 等一切支持S3协议的厂家 | 不支持 |
| 短信 | 采用 sms4j 短信融合包 支持数十种短信厂家 只需在yml配置好厂家密钥即可使用 可多厂家共用 | 不支持 |
| 邮件 | 采用 mail-api 通用协议支持大部分邮件厂商 | 不支持 |
| 接口文档 | 采用 SpringDoc、javadoc 无注解零入侵基于java注释<br/>只需把注释写好 无需再写一大堆的文档注解了 | 采用 Springfox 已停止维护 需要编写大量的注解来支持文档生成 |
| 校验框架 | 采用 Validation 支持注解与工具类校验 注解支持国际化 | 仅支持注解 且注解不支持国际化 |
| Excel框架 | 采用 Alibaba EasyExcel 基于插件化<br/>框架对其增加了很多功能 例如 自动合并相同内容 自动排列布局 字典翻译等 | 基于 POI 手写实现 功能有限 复杂 扩展性差 |
| 工具类框架 | 采用 Hutool、Lombok 上百种工具覆盖90%的使用需求 基于注解自动生成 get set 等简化框架大量代码 | 手写工具稳定性差易出问题 工具数量有限 代码臃肿需自己手写 get set 等 |
| 监控框架 | 采用 SpringBoot-Admin 基于SpringBoot官方 actuator 探针机制<br/>实时监控服务状态 框架还为其扩展了在线日志查看监控 | 无 |
| 链路追踪 | 采用 Apache SkyWalking 还在为请求不知道去哪了 到哪出了问题而烦恼吗<br/>用了它即可实时查看请求经过的每一处每一个节点 | 无 |
| 代码生成器 | 只需设计好表结构 一键生成所有crud代码与页面<br/>降低80%的开发量 把精力都投入到业务设计上<br/>框架为其适配MP、SpringDoc规范化代码 同时支持动态多数据源代码生成 | 代码生成原生结构 只支持单数据源生成 |
| 部署方式 | 支持 Docker 编排 一键搭建所有环境 让开发人员从此不再为搭建环境而烦恼 | 原生jar部署 其他环境需手动下载安装 自行搭建 |
| 项目路径修改 | 提供详细的修改方案文档 并为其做了一些改动 非常简单即可修改成自己想要的 | 需要做很多改造 文档说明有限 |
| 国际化 | 基于请求头动态返回不同语种的文本内容 开发难度低 有对应的工具类 支持大部分注解内容国际化 | 只提供基础功能 其他需自行编写扩展 |
| 代码单例测试 | 提供单例测试 使用方式编写方法与maven多环境单测插件 | 只提供基础功能 其他需自行编写扩展 |
| Demo案例 | 提供框架功能的实际使用案例 单独一个模块提供了很多很全 | 无 |
## 本框架与RuoYi的业务差异
| 业务 | 功能说明 | 本框架 | RuoYi |
|--------|-----------------------------------------|-----|------------------|
| 用户管理 | 用户的管理配置 如:新增用户、分配用户所属部门、角色、岗位等 | 支持 | 支持 |
| 部门管理 | 配置系统组织机构(公司、部门、小组) 树结构展现支持数据权限 | 支持 | 支持 |
| 岗位管理 | 配置系统用户所属担任职务 | 支持 | 支持 |
| 菜单管理 | 配置系统菜单、操作权限、按钮权限标识等 | 支持 | 支持 |
| 角色管理 | 角色菜单权限分配、设置角色按机构进行数据范围权限划分 | 支持 | 支持 |
| 字典管理 | 对系统中经常使用的一些较为固定的数据进行维护 | 支持 | 支持 |
| 参数管理 | 对系统动态配置常用参数 | 支持 | 支持 |
| 通知公告 | 系统通知公告信息发布维护 | 支持 | 支持 |
| 操作日志 | 系统正常操作日志记录和查询 系统异常信息日志记录和查询 | 支持 | 支持 |
| 登录日志 | 系统登录日志记录查询包含登录异常 | 支持 | 支持 |
| 文件管理 | 系统文件展示、上传、下载、删除等管理 | 支持 | 无 |
| 文件配置管理 | 系统文件上传、下载所需要的配置信息动态添加、修改、删除等管理 | 支持 | 无 |
| 在线用户管理 | 已登录系统的在线用户信息监控与强制踢出操作 | 支持 | 支持 |
| 定时任务 | 运行报表、任务管理(添加、修改、删除)、日志管理、执行器管理等 | 支持 | 仅支持任务与日志管理 |
| 代码生成 | 多数据源前后端代码的生成java、html、xml、sql支持CRUD下载 | 支持 | 仅支持单数据源 |
| 系统接口 | 根据业务代码自动生成相关的api接口文档 | 支持 | 支持 |
| 服务监控 | 监视集群系统CPU、内存、磁盘、堆栈、在线日志、Spring相关配置等 | 支持 | 仅支持单机CPU、内存、磁盘监控 |
| 缓存监控 | 对系统的缓存信息查询,命令统计等。 | 支持 | 支持 |
| 在线构建器 | 拖动表单元素生成相应的HTML代码。 | 支持 | 支持 |
| 使用案例 | 系统的一些功能案例 | 支持 | 不支持 |
## 参考文档
使用框架前请仔细阅读文档重点注意事项
<br>
>[初始化项目 必看](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/pages?sort_id=4164117&doc_id=1469725)
>>[https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/pages?sort_id=4164117&doc_id=1469725](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/pages?sort_id=4164117&doc_id=1469725)
>[初始化项目 必看](https://gitee.com/dromara/RuoYi-Vue-Plus/wikis/pages?sort_id=4164117&doc_id=1469725)
>>[https://gitee.com/dromara/RuoYi-Vue-Plus/wikis/pages?sort_id=4164117&doc_id=1469725](https://gitee.com/dromara/RuoYi-Vue-Plus/wikis/pages?sort_id=4164117&doc_id=1469725)
>
>[专栏与视频 入门必看](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/pages?sort_id=5473272&doc_id=1469725)
>>[https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/pages?sort_id=5473272&doc_id=1469725](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/pages?sort_id=5473272&doc_id=1469725)
>[专栏与视频 入门必看](https://gitee.com/dromara/RuoYi-Vue-Plus/wikis/pages?sort_id=5473272&doc_id=1469725)
>>[https://gitee.com/dromara/RuoYi-Vue-Plus/wikis/pages?sort_id=5473272&doc_id=1469725](https://gitee.com/dromara/RuoYi-Vue-Plus/wikis/pages?sort_id=5473272&doc_id=1469725)
>
>[部署项目 必看](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/pages?sort_id=4219382&doc_id=1469725)
>>[https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/pages?sort_id=4219382&doc_id=1469725](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/pages?sort_id=4219382&doc_id=1469725)
>[部署项目 必看](https://gitee.com/dromara/RuoYi-Vue-Plus/wikis/pages?sort_id=4219382&doc_id=1469725)
>>[https://gitee.com/dromara/RuoYi-Vue-Plus/wikis/pages?sort_id=4219382&doc_id=1469725](https://gitee.com/dromara/RuoYi-Vue-Plus/wikis/pages?sort_id=4219382&doc_id=1469725)
>
>[参考文档 Wiki](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/pages)
>>[https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/pages](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/pages)
>[参考文档 Wiki](https://gitee.com/dromara/RuoYi-Vue-Plus/wikis/pages)
>>[https://gitee.com/dromara/RuoYi-Vue-Plus/wikis/pages](https://gitee.com/dromara/RuoYi-Vue-Plus/wikis/pages)
## 软件架构图
@ -83,81 +130,42 @@
### 其他
* 同步升级 RuoYi-Vue
* GitHub 地址 [RuoYi-Vue-Plus-github](https://github.com/JavaLionLi/RuoYi-Vue-Plus)
* 单模块 分支 [RuoYi-Vue-Plus-fast](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/tree/fast/)
* GitHub 地址 [RuoYi-Vue-Plus-github](https://github.com/dromara/RuoYi-Vue-Plus)
* 单模块 分支 [RuoYi-Vue-Plus-fast](https://gitee.com/dromara/RuoYi-Vue-Plus/tree/fast/)
* 微服务 分支 [RuoYi-Cloud-Plus](https://gitee.com/JavaLionLi/RuoYi-Cloud-Plus)
* 用户扩展项目 [扩展项目列表](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/pages?sort_id=4478302&doc_id=1469725)
* 用户扩展项目 [扩展项目列表](https://gitee.com/dromara/RuoYi-Vue-Plus/wikis/pages?sort_id=4478302&doc_id=1469725)
## 加群与捐献
>[加群与捐献](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/加群与捐献?sort_id=4104598)
>>[https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/加群与捐献?sort_id=4104598](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/加群与捐献?sort_id=4104598)
>[加群与捐献](https://gitee.com/dromara/RuoYi-Vue-Plus/wikis/加群与捐献?sort_id=4104598)
>>[https://gitee.com/dromara/RuoYi-Vue-Plus/wikis/加群与捐献?sort_id=4104598](https://gitee.com/dromara/RuoYi-Vue-Plus/wikis/加群与捐献?sort_id=4104598)
## 捐献作者
作者为兼职做开源,平时还需要工作,如果帮到了您可以请作者吃个盒饭
<img src="https://images.gitee.com/uploads/images/2022/0218/213734_b1b8197f_1766278.jpeg" width="300px" height="450px" />
<img src="https://images.gitee.com/uploads/images/2021/0525/101713_3d18b119_1766278.jpeg" width="300px" height="450px" />
## 业务功能
| 功能 | 介绍 |
|---|---|
| 用户管理 | 用户是系统操作者,该功能主要完成系统用户配置。 |
| 部门管理 | 配置系统组织机构(公司、部门、小组),树结构展现支持数据权限。 |
| 岗位管理 | 配置系统用户所属担任职务。 |
| 菜单管理 | 配置系统菜单,操作权限,按钮权限标识等。 |
| 角色管理 | 角色菜单权限分配、设置角色按机构进行数据范围权限划分。 |
| 字典管理 | 对系统中经常使用的一些较为固定的数据进行维护。 |
| 参数管理 | 对系统动态配置常用参数。 |
| 通知公告 | 系统通知公告信息发布维护。 |
| 操作日志 | 系统正常操作日志记录和查询;系统异常信息日志记录和查询。 |
| 登录日志 | 系统登录日志记录查询包含登录异常。 |
| 文件管理 | 系统文件上传、下载等管理。 |
| 定时任务 | 在线(添加、修改、删除)任务调度包含执行结果日志。 |
| 代码生成 | 前后端代码的生成java、html、xml、sql支持CRUD下载 。 |
| 系统接口 | 根据业务代码自动生成相关的api接口文档。 |
| 服务监控 | 监视集群系统CPU、内存、磁盘、堆栈、在线日志、Spring相关配置等。 |
| 缓存监控 | 对系统的缓存信息查询,命令统计等。 |
| 在线构建器 | 拖动表单元素生成相应的HTML代码。 |
| 连接池监视 | 监视当前系统数据库连接池状态可进行分析SQL找出系统性能瓶颈。 |
| 使用案例 | 系统的一些功能案例 |
## 演示图例
<table border="1" cellpadding="1" cellspacing="1" style="width:500px">
<tbody>
<tr>
<td><img src="https://oscimg.oschina.net/oscnet/up-972235bcbe3518dedd351ff0e2ee7d1031c.png" width="1920" /></td>
<td><img src="https://oscimg.oschina.net/oscnet/up-5e0097702fa91e2e36391de8127676a7fa1.png" width="1920" /></td>
</tr>
<tr>
<td>
<p><img src="https://oscimg.oschina.net/oscnet/up-e56e3828f48cd9886d88731766f06d5f3c1.png" width="1920" /></p>
</td>
<td><img src="https://oscimg.oschina.net/oscnet/up-0715990ea1a9f254ec2138fcd063c1f556a.png" width="1920" /></td>
</tr>
<tr>
<td><img src="https://oscimg.oschina.net/oscnet/up-eaf5417ccf921bb64abb959e3d8e290467f.png" width="1920" /></td>
<td><img src="https://oscimg.oschina.net/oscnet/up-fc285cf33095ebf8318de6999af0f473861.png" width="1920" /></td>
</tr>
<tr>
<td><img src="https://oscimg.oschina.net/oscnet/up-60c83fd8bd61c29df6dbf47c88355e9c272.png" width="1920" /></td>
<td><img src="https://oscimg.oschina.net/oscnet/up-7f731948c8b73c7d90f67f9e1c7a534d5c3.png" width="1920" /></td>
</tr>
<tr>
<td><img src="https://oscimg.oschina.net/oscnet/up-e4de89b5e2d20c52d3c3a47f9eb88eb8526.png" width="1920" /></td>
<td><img src="https://oscimg.oschina.net/oscnet/up-8791d823a508eb90e67c604f36f57491a67.png" width="1920" /></td>
</tr>
<tr>
<td><img src="https://oscimg.oschina.net/oscnet/up-4589afd99982ead331785299b894174feb6.png" width="1920" /></td>
<td><img src="https://oscimg.oschina.net/oscnet/up-8ea177cdacaea20995daf2f596b15232561.png" width="1920" /></td>
</tr>
<tr>
<td><img src="https://oscimg.oschina.net/oscnet/up-32d1d04c55c11f74c9129fbbc58399728c4.png" width="1920" /></td>
<td><img src="https://oscimg.oschina.net/oscnet/up-04fa118f7631b7ae6fd72299ca0a1430a63.png" width="1920" /></td>
</tr>
<tr>
<td><img src="https://oscimg.oschina.net/oscnet/up-fe7e85b65827802bfaadf3acd42568b58c7.png" width="1920" /></td>
<td><img src="https://oscimg.oschina.net/oscnet/up-eff2b02a54f8188022d8498cfe6af6fcc06.png" width="1920" /></td>
</tr>
</tbody>
</table>
| | |
|--------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------|
| ![输入图片说明](https://foruda.gitee.com/images/1680077524361362822/270bb429_1766278.png "屏幕截图") | ![输入图片说明](https://foruda.gitee.com/images/1680077619939771291/989bf9b6_1766278.png "屏幕截图") |
| ![输入图片说明](https://foruda.gitee.com/images/1680077681751513929/1c27c5bd_1766278.png "屏幕截图") | ![输入图片说明](https://foruda.gitee.com/images/1680077721559267315/74d63e23_1766278.png "屏幕截图") |
| ![输入图片说明](https://foruda.gitee.com/images/1680077765638904515/1b75d4a6_1766278.png "屏幕截图") | ![输入图片说明](https://foruda.gitee.com/images/1680078026375951297/eded7a4b_1766278.png "屏幕截图") |
| ![输入图片说明](https://foruda.gitee.com/images/1680078237104531207/0eb1b6a7_1766278.png "屏幕截图") | ![输入图片说明](https://foruda.gitee.com/images/1680078254306078709/5931e22f_1766278.png "屏幕截图") |
| ![输入图片说明](https://foruda.gitee.com/images/1680078287971528493/0b9af60a_1766278.png "屏幕截图") | ![输入图片说明](https://foruda.gitee.com/images/1680078308138770249/8d3b6696_1766278.png "屏幕截图") |
| ![输入图片说明](https://foruda.gitee.com/images/1680078352553634393/db5ef880_1766278.png "屏幕截图") | ![输入图片说明](https://foruda.gitee.com/images/1680078378238393374/601e4357_1766278.png "屏幕截图") |
| ![输入图片说明](https://foruda.gitee.com/images/1680078414983206024/2aae27c1_1766278.png "屏幕截图") | ![输入图片说明](https://foruda.gitee.com/images/1680078446738419874/ecce7d59_1766278.png "屏幕截图") |
| ![输入图片说明](https://foruda.gitee.com/images/1680078475971341775/149e8634_1766278.png "屏幕截图") | ![输入图片说明](https://foruda.gitee.com/images/1680078491666717143/3fadece7_1766278.png "屏幕截图") |
| ![输入图片说明](https://foruda.gitee.com/images/1680078558863188826/fb8ced2a_1766278.png "屏幕截图") | ![输入图片说明](https://foruda.gitee.com/images/1680078574561685461/ae68a0b2_1766278.png "屏幕截图") |
| ![输入图片说明](https://foruda.gitee.com/images/1680078594932772013/9d8bfec6_1766278.png "屏幕截图") | ![输入图片说明](https://foruda.gitee.com/images/1680078626493093532/fcfe4ff6_1766278.png "屏幕截图") |
| ![输入图片说明](https://foruda.gitee.com/images/1680078643608812515/0295bd4f_1766278.png "屏幕截图") | ![输入图片说明](https://foruda.gitee.com/images/1680078685196286463/d7612c81_1766278.png "屏幕截图") |
| ![输入图片说明](https://foruda.gitee.com/images/1680078703877318597/56fce0bc_1766278.png "屏幕截图") | ![输入图片说明](https://foruda.gitee.com/images/1680078716586545643/b6dbd68f_1766278.png "屏幕截图") |
| ![输入图片说明](https://foruda.gitee.com/images/1680078734103217688/eb1e6aa6_1766278.png "屏幕截图") | ![输入图片说明](https://foruda.gitee.com/images/1680078759131415480/73c525d8_1766278.png "屏幕截图") |
| ![输入图片说明](https://foruda.gitee.com/images/1680078779416197879/75e3ed02_1766278.png "屏幕截图") | ![输入图片说明](https://foruda.gitee.com/images/1680078802329118061/77e10915_1766278.png "屏幕截图") |
| ![输入图片说明](https://foruda.gitee.com/images/1680078893627848351/34a1c342_1766278.png "屏幕截图") | ![输入图片说明](https://foruda.gitee.com/images/1680078928175016986/f126ec4a_1766278.png "屏幕截图") |
| ![输入图片说明](https://foruda.gitee.com/images/1680078941718318363/b68a0f72_1766278.png "屏幕截图") | ![输入图片说明](https://foruda.gitee.com/images/1680078963175518631/3bb769a1_1766278.png "屏幕截图") |
| ![输入图片说明](https://foruda.gitee.com/images/1680078982294090567/b31c343d_1766278.png "屏幕截图") | ![输入图片说明](https://foruda.gitee.com/images/1680079000642440444/77ca82a9_1766278.png "屏幕截图") |
| ![输入图片说明](https://foruda.gitee.com/images/1680079020995074177/03b7d52e_1766278.png "屏幕截图") | ![输入图片说明](https://foruda.gitee.com/images/1680079039367822173/76811806_1766278.png "屏幕截图") |
| ![输入图片说明](https://foruda.gitee.com/images/1680079274333484664/4dfdc7c0_1766278.png "屏幕截图") | ![输入图片说明](https://foruda.gitee.com/images/1680079290467458224/d6715fcf_1766278.png "屏幕截图") |

265
pom.xml
View File

@ -6,48 +6,76 @@
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-vue-plus</artifactId>
<version>4.3.0</version>
<version>4.8.2</version>
<name>RuoYi-Vue-Plus</name>
<url>https://gitee.com/JavaLionLi/RuoYi-Vue-Plus</url>
<url>https://gitee.com/dromara/RuoYi-Vue-Plus</url>
<description>RuoYi-Vue-Plus后台管理系统</description>
<properties>
<ruoyi-vue-plus.version>4.3.0</ruoyi-vue-plus.version>
<spring-boot.version>2.7.3</spring-boot.version>
<ruoyi-vue-plus.version>4.8.2</ruoyi-vue-plus.version>
<spring-boot.version>2.7.18</spring-boot.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<maven-jar-plugin.version>3.2.2</maven-jar-plugin.version>
<spring-boot.mybatis>2.2.2</spring-boot.mybatis>
<druid.version>1.2.12</druid.version>
<springdoc.version>1.6.11</springdoc.version>
<poi.version>5.2.2</poi.version>
<easyexcel.version>3.1.1</easyexcel.version>
<springdoc.version>1.6.15</springdoc.version>
<poi.version>5.2.3</poi.version>
<easyexcel.version>3.3.2</easyexcel.version>
<velocity.version>2.3</velocity.version>
<satoken.version>1.30.0</satoken.version>
<mybatis-plus.version>3.5.2</mybatis-plus.version>
<satoken.version>1.37.0</satoken.version>
<mybatis-plus.version>3.5.4</mybatis-plus.version>
<p6spy.version>3.9.1</p6spy.version>
<hutool.version>5.8.6</hutool.version>
<hutool.version>5.8.22</hutool.version>
<okhttp.version>4.10.0</okhttp.version>
<spring-boot-admin.version>2.7.4</spring-boot-admin.version>
<redisson.version>3.17.6</redisson.version>
<lock4j.version>2.2.2</lock4j.version>
<spring-boot-admin.version>2.7.11</spring-boot-admin.version>
<redisson.version>3.20.1</redisson.version>
<lock4j.version>2.2.3</lock4j.version>
<dynamic-ds.version>3.5.2</dynamic-ds.version>
<tlog.version>1.4.3</tlog.version>
<xxl-job.version>2.3.1</xxl-job.version>
<lombok.version>1.18.24</lombok.version>
<!-- 统一 guava 版本 解决隐式漏洞问题 -->
<guava.version>31.1-jre</guava.version>
<alibaba-ttl.version>2.14.2</alibaba-ttl.version>
<xxl-job.version>2.4.0</xxl-job.version>
<lombok.version>1.18.30</lombok.version>
<bouncycastle.version>1.72</bouncycastle.version>
<!-- 离线IP地址定位库 -->
<ip2region.version>2.7.0</ip2region.version>
<!-- OSS 配置 -->
<aws-java-sdk-s3.version>1.12.300</aws-java-sdk-s3.version>
<aws-java-sdk-s3.version>1.12.540</aws-java-sdk-s3.version>
<!-- SMS 配置 -->
<aliyun.sms.version>2.0.18</aliyun.sms.version>
<tencent.sms.version>3.1.591</tencent.sms.version>
<sms4j.version>2.2.0</sms4j.version>
</properties>
<profiles>
<profile>
<id>local</id>
<properties>
<!-- 环境标识,需要与配置文件的名称相对应 -->
<profiles.active>local</profiles.active>
<logging.level>info</logging.level>
</properties>
</profile>
<profile>
<id>dev</id>
<properties>
<!-- 环境标识,需要与配置文件的名称相对应 -->
<profiles.active>dev</profiles.active>
<logging.level>info</logging.level>
</properties>
<activation>
<!-- 默认环境 -->
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<profile>
<id>prod</id>
<properties>
<profiles.active>prod</profiles.active>
<logging.level>warn</logging.level>
</properties>
</profile>
</profiles>
<!-- 依赖声明 -->
<dependencyManagement>
<dependencies>
@ -70,13 +98,6 @@
<scope>import</scope>
</dependency>
<!-- 阿里数据库连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>${druid.version}</version>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-webmvc-core</artifactId>
@ -155,11 +176,7 @@
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-extension</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<!-- sql性能分析插件 -->
<dependency>
<groupId>p6spy</groupId>
@ -179,16 +196,11 @@
<version>${aws-java-sdk-s3.version}</version>
</dependency>
<!--短信sms4j-->
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>dysmsapi20170525</artifactId>
<version>${aliyun.sms.version}</version>
</dependency>
<dependency>
<groupId>com.tencentcloudapi</groupId>
<artifactId>tencentcloud-sdk-java</artifactId>
<version>${tencent.sms.version}</version>
<groupId>org.dromara.sms4j</groupId>
<artifactId>sms4j-spring-boot-starter</artifactId>
<version>${sms4j.version}</version>
</dependency>
<dependency>
@ -207,7 +219,19 @@
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>${redisson.version}</version>
<exclusions>
<exclusion>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-data-30</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-data-27</artifactId>
<version>${redisson.version}</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>lock4j-redisson-spring-boot-starter</artifactId>
@ -222,108 +246,31 @@
</dependency>
<dependency>
<groupId>com.yomahub</groupId>
<artifactId>tlog-web-spring-boot-starter</artifactId>
<version>${tlog.version}</version>
<exclusions>
<exclusion>
<artifactId>log4j</artifactId>
<groupId>log4j</groupId>
</exclusion>
<exclusion>
<artifactId>dom4j</artifactId>
<groupId>dom4j</groupId>
</exclusion>
<exclusion>
<artifactId>commons-beanutils</artifactId>
<groupId>commons-beanutils</groupId>
</exclusion>
</exclusions>
<groupId>com.alibaba</groupId>
<artifactId>transmittable-thread-local</artifactId>
<version>${alibaba-ttl.version}</version>
</dependency>
<!-- 离线IP地址定位库 ip2region -->
<dependency>
<groupId>com.yomahub</groupId>
<artifactId>tlog-xxljob-spring-boot-starter</artifactId>
<version>${tlog.version}</version>
<groupId>org.lionsoul</groupId>
<artifactId>ip2region</artifactId>
<version>${ip2region.version}</version>
</dependency>
<!-- 统一 guava 版本 解决隐式漏洞问题 -->
<!-- 加密包引入 -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava.version}</version>
</dependency>
<!-- 定时任务 -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-job</artifactId>
<version>${ruoyi-vue-plus.version}</version>
</dependency>
<!-- 代码生成-->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-generator</artifactId>
<version>${ruoyi-vue-plus.version}</version>
</dependency>
<!-- 核心模块-->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-framework</artifactId>
<version>${ruoyi-vue-plus.version}</version>
</dependency>
<!-- 系统模块-->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-system</artifactId>
<version>${ruoyi-vue-plus.version}</version>
</dependency>
<!-- 通用工具-->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId>
<version>${ruoyi-vue-plus.version}</version>
</dependency>
<!-- OSS对象存储模块 -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-oss</artifactId>
<version>${ruoyi-vue-plus.version}</version>
</dependency>
<!-- SMS短信模块 -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-sms</artifactId>
<version>${ruoyi-vue-plus.version}</version>
</dependency>
<!-- demo模块 -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-demo</artifactId>
<version>${ruoyi-vue-plus.version}</version>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15to18</artifactId>
<version>${bouncycastle.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<modules>
<module>ruoyi-admin</module>
<module>ruoyi-framework</module>
<module>ruoyi-system</module>
<module>ruoyi-job</module>
<module>ruoyi-generator</module>
<module>ruoyi-common</module>
<module>ruoyi-demo</module>
<module>ruoyi</module>
<module>ruoyi-extend</module>
<module>ruoyi-oss</module>
<module>ruoyi-sms</module>
</modules>
<packaging>pom</packaging>
@ -356,6 +303,19 @@
</annotationProcessorPaths>
</configuration>
</plugin>
<!-- 单元测试使用 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.2</version>
<configuration>
<argLine>-Dfile.encoding=UTF-8</argLine>
<!-- 根据打包环境执行对应的@Tag测试方法 -->
<groups>${profiles.active}</groups>
<!-- 排除标签 -->
<excludedGroups>exclude</excludedGroups>
</configuration>
</plugin>
</plugins>
<resources>
<resource>
@ -380,8 +340,8 @@
<repositories>
<repository>
<id>public</id>
<name>aliyun nexus</name>
<url>https://maven.aliyun.com/repository/public/</url>
<name>huawei nexus</name>
<url>https://mirrors.huaweicloud.com/repository/maven/</url>
<releases>
<enabled>true</enabled>
</releases>
@ -391,8 +351,8 @@
<pluginRepositories>
<pluginRepository>
<id>public</id>
<name>aliyun nexus</name>
<url>https://maven.aliyun.com/repository/public/</url>
<name>huawei nexus</name>
<url>https://mirrors.huaweicloud.com/repository/maven/</url>
<releases>
<enabled>true</enabled>
</releases>
@ -402,35 +362,6 @@
</pluginRepository>
</pluginRepositories>
<profiles>
<profile>
<id>local</id>
<properties>
<!-- 环境标识,需要与配置文件的名称相对应 -->
<profiles.active>local</profiles.active>
<logging.level>debug</logging.level>
</properties>
</profile>
<profile>
<id>dev</id>
<properties>
<!-- 环境标识,需要与配置文件的名称相对应 -->
<profiles.active>dev</profiles.active>
<logging.level>debug</logging.level>
</properties>
<activation>
<!-- 默认环境 -->
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<profile>
<id>prod</id>
<properties>
<profiles.active>prod</profiles.active>
<logging.level>warn</logging.level>
</properties>
</profile>
</profiles>
</project>

View File

@ -1,17 +0,0 @@
FROM anapsix/alpine-java:8_server-jre_unlimited
MAINTAINER Lion Li
RUN mkdir -p /ruoyi/server
RUN mkdir -p /ruoyi/server/logs
RUN mkdir -p /ruoyi/server/temp
WORKDIR /ruoyi/server
ENV SERVER_PORT=8080
EXPOSE ${SERVER_PORT}
ADD ./target/ruoyi-admin.jar ./app.jar
ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom", "-Dserver.port=${SERVER_PORT}","-jar", "app.jar"]

View File

@ -1,113 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>ruoyi-vue-plus</artifactId>
<groupId>com.ruoyi</groupId>
<version>4.3.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>
<artifactId>ruoyi-admin</artifactId>
<description>
web服务入口
</description>
<dependencies>
<!-- spring-boot-devtools -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional> <!-- 表示依赖不会传递 -->
</dependency>
<!-- Mysql驱动包 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- Oracle -->
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc8</artifactId>
</dependency>
<!-- PostgreSql -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
</dependency>
<!-- SqlServer -->
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
</dependency>
<!-- 核心模块-->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-framework</artifactId>
</dependency>
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-system</artifactId>
</dependency>
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-job</artifactId>
</dependency>
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-oss</artifactId>
</dependency>
<!-- 代码生成-->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-generator</artifactId>
</dependency>
<!-- demo模块 -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-demo</artifactId>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
<configuration>
<fork>true</fork> <!-- 如果没有该配置devtools不会生效 -->
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
<warName>${project.artifactId}</warName>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -1,157 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>ruoyi-vue-plus</artifactId>
<groupId>com.ruoyi</groupId>
<version>4.3.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ruoyi-common</artifactId>
<description>
common通用工具
</description>
<dependencies>
<!-- Spring框架基本的核心工具 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
<!-- SpringWeb模块 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
<!-- Sa-Token 权限认证, 在线文档http://sa-token.dev33.cn/ -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot-starter</artifactId>
</dependency>
<!-- Sa-Token 整合 jwt -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-jwt</artifactId>
</dependency>
<!-- 自定义验证注解 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<!--常用工具类 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<!-- JSON工具类 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
</dependency>
<!-- yml解析器 -->
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
</dependency>
<!-- servlet包 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-extension</artifactId>
</dependency>
<!-- dynamic-datasource 多数据源-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-core</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-http</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-captcha</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-jwt</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-extra</artifactId>
</dependency>
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>jakarta.mail</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-webmvc-core</artifactId>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-javadoc</artifactId>
</dependency>
<!-- 自动生成YML配置关联JSON文件 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</dependency>
<!--redisson-->
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>lock4j-redisson-spring-boot-starter</artifactId>
</dependency>
</dependencies>
</project>

View File

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

View File

@ -1,86 +0,0 @@
package com.ruoyi.common.core.domain;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.sql.SqlUtil;
import lombok.Data;
import java.io.Serializable;
/**
* 分页查询实体类
*
* @author Lion Li
*/
@Data
public class PageQuery implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 分页大小
*/
private Integer pageSize;
/**
* 当前页数
*/
private Integer pageNum;
/**
* 排序列
*/
private String orderByColumn;
/**
* 排序的方向desc或者asc
*/
private String isAsc;
/**
* 当前记录起始索引 默认值
*/
public static final int DEFAULT_PAGE_NUM = 1;
/**
* 每页显示记录数 默认值 默认查全部
*/
public static final int DEFAULT_PAGE_SIZE = Integer.MAX_VALUE;
public <T> Page<T> build() {
Integer pageNum = ObjectUtil.defaultIfNull(getPageNum(), DEFAULT_PAGE_NUM);
Integer pageSize = ObjectUtil.defaultIfNull(getPageSize(), DEFAULT_PAGE_SIZE);
if (pageNum <= 0) {
pageNum = DEFAULT_PAGE_NUM;
}
Page<T> page = new Page<>(pageNum, pageSize);
OrderItem orderItem = buildOrderItem();
if (ObjectUtil.isNotNull(orderItem)) {
page.addOrder(orderItem);
}
return page;
}
private OrderItem buildOrderItem() {
// 兼容前端排序类型
if ("ascending".equals(isAsc)) {
isAsc = "asc";
} else if ("descending".equals(isAsc)) {
isAsc = "desc";
}
if (StringUtils.isNotBlank(orderByColumn)) {
String orderBy = SqlUtil.escapeOrderBySql(orderByColumn);
orderBy = StringUtils.toUnderScoreCase(orderBy);
if ("asc".equals(isAsc)) {
return OrderItem.asc(orderBy);
} else if ("desc".equals(isAsc)) {
return OrderItem.desc(orderBy);
}
}
return null;
}
}

View File

@ -1,14 +0,0 @@
package com.ruoyi.common.core.service;
import javax.servlet.http.HttpServletRequest;
/**
* 通用 系统访问日志
*
* @author Lion Li
*/
public interface LogininforService {
void recordLogininfor(String username, String status, String message,
HttpServletRequest request, Object... args);
}

View File

@ -1,15 +0,0 @@
package com.ruoyi.common.core.service;
import com.ruoyi.common.core.domain.dto.OperLogDTO;
import org.springframework.scheduling.annotation.Async;
/**
* 通用 操作日志
*
* @author Lion Li
*/
public interface OperLogService {
@Async
void recordOper(OperLogDTO operLogDTO);
}

View File

@ -1,114 +0,0 @@
package com.ruoyi.common.excel;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.write.merge.AbstractMergeStrategy;
import com.ruoyi.common.annotation.CellMerge;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 列值重复合并策略
*
* @author Lion Li
*/
@AllArgsConstructor
@Slf4j
public class CellMergeStrategy extends AbstractMergeStrategy {
private List<?> list;
private boolean hasTitle;
@Override
protected void merge(Sheet sheet, Cell cell, Head head, Integer relativeRowIndex) {
List<CellRangeAddress> cellList = handle(list, hasTitle);
// judge the list is not null
if (CollectionUtils.isNotEmpty(cellList)) {
// the judge is necessary
if (cell.getRowIndex() == 1 && cell.getColumnIndex() == 0) {
for (CellRangeAddress item : cellList) {
sheet.addMergedRegion(item);
}
}
}
}
@SneakyThrows
private static List<CellRangeAddress> handle(List<?> list, boolean hasTitle) {
List<CellRangeAddress> cellList = new ArrayList<>();
if (CollectionUtils.isEmpty(list)) {
return cellList;
}
Class<?> clazz = list.get(0).getClass();
Field[] fields = clazz.getDeclaredFields();
// 有注解的字段
List<Field> mergeFields = new ArrayList<>();
List<Integer> mergeFieldsIndex = new ArrayList<>();
for (int i = 0; i < fields.length; i++) {
Field field = fields[i];
if (field.isAnnotationPresent(CellMerge.class)) {
CellMerge cm = field.getAnnotation(CellMerge.class);
mergeFields.add(field);
mergeFieldsIndex.add(cm.index() == -1 ? i : cm.index());
}
}
// 行合并开始下标
int rowIndex = hasTitle ? 1 : 0;
Map<Field, RepeatCell> map = new HashMap<>();
// 生成两两合并单元格
for (int i = 0; i < list.size(); i++) {
for (int j = 0; j < mergeFields.size(); j++) {
Field field = mergeFields.get(j);
String name = field.getName();
String methodName = "get" + name.substring(0, 1).toUpperCase() + name.substring(1);
Method readMethod = clazz.getMethod(methodName);
Object val = readMethod.invoke(list.get(i));
int colNum = mergeFieldsIndex.get(j);
if (!map.containsKey(field)) {
map.put(field, new RepeatCell(val, i));
} else {
RepeatCell repeatCell = map.get(field);
Object cellValue = repeatCell.getValue();
if (cellValue == null || "".equals(cellValue)) {
// 空值跳过不合并
continue;
}
if (cellValue != val) {
if (i - repeatCell.getCurrent() > 1) {
cellList.add(new CellRangeAddress(repeatCell.getCurrent() + rowIndex, i + rowIndex - 1, colNum, colNum));
}
map.put(field, new RepeatCell(val, i));
} else if (i == list.size() - 1) {
if (i > repeatCell.getCurrent()) {
cellList.add(new CellRangeAddress(repeatCell.getCurrent() + rowIndex, i + rowIndex, colNum, colNum));
}
}
}
}
}
return cellList;
}
@Data
@AllArgsConstructor
static class RepeatCell {
private Object value;
private int current;
}
}

View File

@ -1,60 +0,0 @@
package com.ruoyi.common.utils.ip;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.net.NetUtil;
import cn.hutool.http.HtmlUtil;
import cn.hutool.http.HttpUtil;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.utils.JsonUtils;
import com.ruoyi.common.utils.StringUtils;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
/**
* 获取地址类
*
* @author Lion Li
*/
@Slf4j
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class AddressUtils {
// IP地址查询
public static final String IP_URL = "http://whois.pconline.com.cn/ipJson.jsp";
// 未知地址
public static final String UNKNOWN = "XX XX";
public static String getRealAddressByIP(String ip) {
String address = UNKNOWN;
if (StringUtils.isBlank(ip)) {
return address;
}
// 内网不查询
ip = "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : HtmlUtil.cleanHtmlTag(ip);
if (NetUtil.isInnerIP(ip)) {
return "内网IP";
}
if (RuoYiConfig.isAddressEnabled()) {
try {
String rspStr = HttpUtil.createGet(IP_URL)
.body("ip=" + ip + "&json=true", Constants.GBK)
.execute()
.body();
if (StringUtils.isEmpty(rspStr)) {
log.error("获取地理位置异常 {}", ip);
return UNKNOWN;
}
Dict obj = JsonUtils.parseMap(rspStr);
String region = obj.getStr("pro");
String city = obj.getStr("city");
return String.format("%s %s", region, city);
} catch (Exception e) {
log.error("获取地理位置异常 {}", ip);
}
}
return UNKNOWN;
}
}

View File

@ -1,44 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>ruoyi-vue-plus</artifactId>
<groupId>com.ruoyi</groupId>
<version>4.3.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ruoyi-demo</artifactId>
<description>
demo模块
</description>
<dependencies>
<!-- 通用工具-->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId>
</dependency>
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-sms</artifactId>
</dependency>
<!-- 短信 用哪个导入哪个依赖 -->
<!-- <dependency>-->
<!-- <groupId>com.aliyun</groupId>-->
<!-- <artifactId>dysmsapi20170525</artifactId>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>com.tencentcloudapi</groupId>-->
<!-- <artifactId>tencentcloud-sdk-java</artifactId>-->
<!-- </dependency>-->
</dependencies>
</project>

View File

@ -1,76 +0,0 @@
package com.ruoyi.demo.controller;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.sms.config.properties.SmsProperties;
import com.ruoyi.sms.core.SmsTemplate;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
/**
* 短信演示案例
* 请先阅读文档 否则无法使用
*
* @author Lion Li
* @version 4.2.0
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/demo/sms")
public class SmsController {
private final SmsProperties smsProperties;
// private final SmsTemplate smsTemplate; // 可以使用spring注入
// private final AliyunSmsTemplate smsTemplate; // 也可以注入某个厂家的模板工具
/**
* 发送短信Aliyun
*
* @param phones 电话号
* @param templateId 模板ID
*/
@GetMapping("/sendAliyun")
public R<Object> sendAliyun(String phones, String templateId) {
if (!smsProperties.getEnabled()) {
return R.fail("当前系统没有开启短信功能!");
}
if (!SpringUtils.containsBean("aliyunSmsTemplate")) {
return R.fail("阿里云依赖未引入!");
}
SmsTemplate smsTemplate = SpringUtils.getBean(SmsTemplate.class);
Map<String, String> map = new HashMap<>(1);
map.put("code", "1234");
Object send = smsTemplate.send(phones, templateId, map);
return R.ok(send);
}
/**
* 发送短信Tencent
*
* @param phones 电话号
* @param templateId 模板ID
*/
@GetMapping("/sendTencent")
public R<Object> sendTencent(String phones, String templateId) {
if (!smsProperties.getEnabled()) {
return R.fail("当前系统没有开启短信功能!");
}
if (!SpringUtils.containsBean("tencentSmsTemplate")) {
return R.fail("腾讯云依赖未引入!");
}
SmsTemplate smsTemplate = SpringUtils.getBean(SmsTemplate.class);
Map<String, String> map = new HashMap<>(1);
// map.put("2", "测试测试");
map.put("1", "1234");
Object send = smsTemplate.send(phones, templateId, map);
return R.ok(send);
}
}

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>ruoyi-vue-plus</artifactId>
<groupId>com.ruoyi</groupId>
<version>4.3.0</version>
<version>4.8.2</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ruoyi-extend</artifactId>

View File

@ -2,7 +2,6 @@ FROM anapsix/alpine-java:8_server-jre_unlimited
MAINTAINER Lion Li
RUN mkdir -p /ruoyi/monitor
RUN mkdir -p /ruoyi/monitor/logs
WORKDIR /ruoyi/monitor

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>ruoyi-extend</artifactId>
<groupId>com.ruoyi</groupId>
<version>4.3.0</version>
<version>4.8.2</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>

View File

@ -6,6 +6,9 @@ spring:
profiles:
active: @profiles.active@
logging:
config: classpath:logback-plus.xml
--- # 监控中心服务端配置
spring:
security:

View File

@ -2,7 +2,6 @@ FROM anapsix/alpine-java:8_server-jre_unlimited
MAINTAINER Lion Li
RUN mkdir -p /ruoyi/xxljob
RUN mkdir -p /ruoyi/xxljob/logs
WORKDIR /ruoyi/xxljob
@ -14,4 +13,4 @@ EXPOSE 9100
ADD ./target/ruoyi-xxl-job-admin.jar ./app.jar
ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "app.jar"]
ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "app.jar"]

View File

@ -4,7 +4,7 @@
<parent>
<artifactId>ruoyi-extend</artifactId>
<groupId>com.ruoyi</groupId>
<version>4.3.0</version>
<version>4.8.2</version>
</parent>
<artifactId>ruoyi-xxl-job-admin</artifactId>
<packaging>jar</packaging>
@ -64,8 +64,8 @@
</dependency>
<!-- mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
</dependency>
<dependency>

View File

@ -1,5 +1,6 @@
package com.xxl.job.admin.controller;
import com.xxl.job.admin.controller.annotation.PermissionLimit;
import com.xxl.job.admin.core.model.XxlJobGroup;
import com.xxl.job.admin.core.model.XxlJobRegistry;
import com.xxl.job.admin.core.util.I18nUtil;
@ -35,12 +36,14 @@ public class JobGroupController {
private XxlJobRegistryDao xxlJobRegistryDao;
@RequestMapping
@PermissionLimit(adminuser = true)
public String index(Model model) {
return "jobgroup/jobgroup.index";
}
@RequestMapping("/pageList")
@ResponseBody
@PermissionLimit(adminuser = true)
public Map<String, Object> pageList(HttpServletRequest request,
@RequestParam(required = false, defaultValue = "0") int start,
@RequestParam(required = false, defaultValue = "10") int length,
@ -60,6 +63,7 @@ public class JobGroupController {
@RequestMapping("/save")
@ResponseBody
@PermissionLimit(adminuser = true)
public ReturnT<String> save(XxlJobGroup xxlJobGroup) {
// valid
@ -103,6 +107,7 @@ public class JobGroupController {
@RequestMapping("/update")
@ResponseBody
@PermissionLimit(adminuser = true)
public ReturnT<String> update(XxlJobGroup xxlJobGroup) {
// valid
if (xxlJobGroup.getAppname() == null || xxlJobGroup.getAppname().trim().length() == 0) {
@ -171,6 +176,7 @@ public class JobGroupController {
@RequestMapping("/remove")
@ResponseBody
@PermissionLimit(adminuser = true)
public ReturnT<String> remove(int id) {
// valid
@ -190,6 +196,7 @@ public class JobGroupController {
@RequestMapping("/loadById")
@ResponseBody
@PermissionLimit(adminuser = true)
public ReturnT<XxlJobGroup> loadById(int id) {
XxlJobGroup jobGroup = xxlJobGroupDao.load(id);
return jobGroup != null ? new ReturnT<XxlJobGroup>(jobGroup) : new ReturnT<XxlJobGroup>(ReturnT.FAIL_CODE, null);

View File

@ -130,22 +130,26 @@ public class JobLogController {
model.addAttribute("triggerCode", jobLog.getTriggerCode());
model.addAttribute("handleCode", jobLog.getHandleCode());
model.addAttribute("executorAddress", jobLog.getExecutorAddress());
model.addAttribute("triggerTime", jobLog.getTriggerTime().getTime());
model.addAttribute("logId", jobLog.getId());
return "joblog/joblog.detail";
}
@RequestMapping("/logDetailCat")
@ResponseBody
public ReturnT<LogResult> logDetailCat(String executorAddress, long triggerTime, long logId, int fromLineNum) {
public ReturnT<LogResult> logDetailCat(long logId, int fromLineNum) {
try {
ExecutorBiz executorBiz = XxlJobScheduler.getExecutorBiz(executorAddress);
ReturnT<LogResult> logResult = executorBiz.log(new LogParam(triggerTime, logId, fromLineNum));
// valid
XxlJobLog jobLog = xxlJobLogDao.load(logId); // todo, need to improve performance
if (jobLog == null) {
return new ReturnT<LogResult>(ReturnT.FAIL_CODE, I18nUtil.getString("joblog_logid_unvalid"));
}
// log cat
ExecutorBiz executorBiz = XxlJobScheduler.getExecutorBiz(jobLog.getExecutorAddress());
ReturnT<LogResult> logResult = executorBiz.log(new LogParam(jobLog.getTriggerTime().getTime(), logId, fromLineNum));
// is end
if (logResult.getContent() != null && logResult.getContent().getFromLineNum() > logResult.getContent().getToLineNum()) {
XxlJobLog jobLog = xxlJobLogDao.load(logId);
if (jobLog.getHandleCode() > 0) {
logResult.getContent().setEnd(true);
}

View File

@ -16,6 +16,9 @@ spring:
resources:
static-locations: classpath:/static/
logging:
config: classpath:logback-plus.xml
--- # mybatis 配置
mybatis:
mapper-locations: classpath:/mybatis-mapper/*Mapper.xml

View File

@ -1,6 +1,6 @@
admin_name=Scheduling Center
admin_name_full=Distributed Task Scheduling Platform XXL-JOB
admin_version=2.3.1
admin_version=2.4.0
admin_i18n=en
## system

View File

@ -1,6 +1,6 @@
admin_name=任务调度中心
admin_name_full=分布式任务调度平台XXL-JOB
admin_version=2.3.1
admin_version=2.4.0
admin_i18n=
## system

View File

@ -1,6 +1,6 @@
admin_name=任務調度中心
admin_name_full=分布式任務調度平臺XXL-JOB
admin_version=2.3.1
admin_version=2.4.0
admin_i18n=
## system

View File

@ -25,8 +25,6 @@ $(function() {
async: false, // sync, make log ordered
url : base_url + '/joblog/logDetailCat',
data : {
"executorAddress":executorAddress,
"triggerTime":triggerTime,
"logId":logId,
"fromLineNum":fromLineNum
},

View File

@ -62,11 +62,9 @@
// 参数
var triggerCode = '${triggerCode}';
var handleCode = '${handleCode}';
var executorAddress = '${executorAddress!}';
var triggerTime = '${triggerTime?c}';
var logId = '${logId}';
</script>
<script src="${request.contextPath}/static/js/joblog.detail.1.js"></script>
</body>
</html>
</html>

View File

@ -1,78 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>ruoyi-vue-plus</artifactId>
<groupId>com.ruoyi</groupId>
<version>4.3.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ruoyi-framework</artifactId>
<description>
framework框架核心
</description>
<dependencies>
<!-- SpringBoot Web容器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<artifactId>spring-boot-starter-tomcat</artifactId>
<groupId>org.springframework.boot</groupId>
</exclusion>
</exclusions>
</dependency>
<!-- web 容器使用 undertow 性能更强 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
<!-- SpringBoot 拦截器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!-- 阿里数据库连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
</dependency>
<!-- sql性能分析插件 -->
<dependency>
<groupId>p6spy</groupId>
<artifactId>p6spy</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
</dependency>
<!-- 系统模块-->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId>
</dependency>
<dependency>
<groupId>com.yomahub</groupId>
<artifactId>tlog-web-spring-boot-starter</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -1,66 +0,0 @@
package com.ruoyi.framework.aspectj;
import com.ruoyi.common.annotation.RateLimiter;
import com.ruoyi.common.enums.LimitType;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.MessageUtils;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.redis.RedisUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.redisson.api.RateType;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
/**
* 限流处理
*
* @author Lion Li
*/
@Slf4j
@Aspect
@Component
public class RateLimiterAspect {
@Before("@annotation(rateLimiter)")
public void doBefore(JoinPoint point, RateLimiter rateLimiter) throws Throwable {
int time = rateLimiter.time();
int count = rateLimiter.count();
String combineKey = getCombineKey(rateLimiter, point);
try {
RateType rateType = RateType.OVERALL;
if (rateLimiter.limitType() == LimitType.CLUSTER) {
rateType = RateType.PER_CLIENT;
}
long number = RedisUtils.rateLimiter(combineKey, rateType, count, time);
if (number == -1) {
throw new ServiceException(MessageUtils.message("rate.limiter.message"));
}
log.info("限制令牌 => {}, 剩余令牌 => {}, 缓存key => '{}'", count, number, combineKey);
} catch (ServiceException e) {
throw e;
} catch (Exception e) {
throw new RuntimeException("服务器限流异常,请稍候再试");
}
}
public String getCombineKey(RateLimiter rateLimiter, JoinPoint point) {
StringBuilder stringBuffer = new StringBuilder(rateLimiter.key());
if (rateLimiter.limitType() == LimitType.IP) {
// 获取请求ip
stringBuffer.append(ServletUtils.getClientIP()).append("-");
} else if (rateLimiter.limitType() == LimitType.CLUSTER) {
// 获取客户端实例id
stringBuffer.append(RedisUtils.getClient().getId()).append("-");
}
MethodSignature signature = (MethodSignature) point.getSignature();
Method method = signature.getMethod();
Class<?> targetClass = method.getDeclaringClass();
stringBuffer.append(targetClass.getName()).append("-").append(method.getName());
return stringBuffer.toString();
}
}

View File

@ -1,63 +0,0 @@
package com.ruoyi.framework.config;
import com.alibaba.druid.spring.boot.autoconfigure.properties.DruidStatProperties;
import com.alibaba.druid.util.Utils;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.servlet.*;
import java.io.IOException;
/**
* druid 配置多数据源
*
* @author ruoyi
*/
@Configuration
public class DruidConfig {
/**
* 去除监控页面底部的广告
*/
@SuppressWarnings({"rawtypes", "unchecked"})
@Bean
@ConditionalOnProperty(name = "spring.datasource.druid.statViewServlet.enabled", havingValue = "true")
public FilterRegistrationBean removeDruidFilterRegistrationBean(DruidStatProperties properties) {
// 获取web监控页面的参数
DruidStatProperties.StatViewServlet config = properties.getStatViewServlet();
// 提取common.js的配置路径
String pattern = config.getUrlPattern() != null ? config.getUrlPattern() : "/druid/*";
String commonJsPattern = pattern.replaceAll("\\*", "js/common.js");
final String filePath = "support/http/resources/js/common.js";
// 创建filter进行过滤
Filter filter = new Filter() {
@Override
public void init(javax.servlet.FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
chain.doFilter(request, response);
// 重置缓冲区,响应头不会被重置
// response.resetBuffer();
// 获取common.js
String text = Utils.readFromResource(filePath);
// 正则替换banner, 除去底部的广告信息
text = text.replaceAll("<a.*?banner\"></a><br/>", "");
text = text.replaceAll("powered.*?shrek.wang</a>", "");
response.getWriter().write(text);
}
@Override
public void destroy() {
}
};
FilterRegistrationBean registrationBean = new FilterRegistrationBean();
registrationBean.setFilter(filter);
registrationBean.addUrlPatterns(commonJsPattern);
return registrationBean;
}
}

View File

@ -1,18 +0,0 @@
package com.ruoyi.framework.config;
import com.yomahub.tlog.springboot.TLogWebAutoConfiguration;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Configuration;
/**
* 整合 TLog 框架配置
*
* @author Lion Li
* @since 3.3.0
*/
@Configuration
// 排除 web 自动配置 自定义实现
@EnableAutoConfiguration(exclude = TLogWebAutoConfiguration.class)
public class TLogConfig {
}

View File

@ -1,62 +0,0 @@
package com.ruoyi.framework.config.properties;
import cn.hutool.core.util.ReUtil;
import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.utils.spring.SpringUtils;
import lombok.Getter;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.annotation.Lazy;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import org.springframework.web.util.pattern.PathPattern;
import java.util.*;
import java.util.regex.Pattern;
/**
* 设置注解允许匿名访问的url
*
* @author Lion Li
*/
@Lazy
@Component
public class ExcludeUrlProperties implements InitializingBean {
private static final Pattern PATTERN = Pattern.compile("\\{(.*?)\\}");
@Getter
private final List<String> excludes = new ArrayList<>();
@Override
public void afterPropertiesSet() {
String asterisk = "*";
RequestMappingHandlerMapping mapping = SpringUtils.getBean("requestMappingHandlerMapping", RequestMappingHandlerMapping.class);
Map<RequestMappingInfo, HandlerMethod> map = mapping.getHandlerMethods();
map.keySet().forEach(info -> {
HandlerMethod handlerMethod = map.get(info);
// 获取方法上边的注解 替代path variable 为 *
Anonymous method = AnnotationUtils.findAnnotation(handlerMethod.getMethod(), Anonymous.class);
Optional.ofNullable(method).ifPresent(anonymous -> {
Set<PathPattern> patterns = info.getPathPatternsCondition().getPatterns();
patterns.forEach(url -> {
excludes.add(ReUtil.replaceAll(url.getPatternString(), PATTERN, asterisk));
});
});
// 获取类上边的注解, 替代path variable 为 *
Anonymous controller = AnnotationUtils.findAnnotation(handlerMethod.getBeanType(), Anonymous.class);
Optional.ofNullable(controller).ifPresent(anonymous -> {
Set<PathPattern> patterns = info.getPathPatternsCondition().getPatterns();
patterns.forEach(url -> {
excludes.add(ReUtil.replaceAll(url.getPatternString(), PATTERN, asterisk));
});
});
});
}
}

View File

@ -1,34 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>ruoyi-vue-plus</artifactId>
<groupId>com.ruoyi</groupId>
<version>4.3.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ruoyi-generator</artifactId>
<description>
generator代码生成
</description>
<dependencies>
<!--velocity代码生成使用模板 -->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
</dependency>
<!-- 通用工具-->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -1,3 +0,0 @@
java包使用 `.` 分割 resource 目录使用 `/` 分割
<br>
此文件目的 防止文件夹粘连找不到 `xml` 文件

View File

@ -1 +0,0 @@
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD>õ<EFBFBD><EFBFBD><EFBFBD>RuoYi-Vue3ǰ<33>ˣ<EFBFBD><CBA3><EFBFBD>ô<EFBFBD><C3B4>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD>һ<EFBFBD>´<EFBFBD>Ŀ¼<C4BF><C2BC>ģ<EFBFBD><C4A3>index.vue.vm<76><6D>index-tree.vue.vm<76>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD>ϼ<EFBFBD>vueĿ¼<C4BF><C2BC>

View File

@ -1,39 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>ruoyi-vue-plus</artifactId>
<groupId>com.ruoyi</groupId>
<version>4.3.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>
<artifactId>ruoyi-job</artifactId>
<description>
任务调度
</description>
<dependencies>
<!-- 通用工具-->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId>
</dependency>
<!-- xxl-job-core -->
<dependency>
<groupId>com.xuxueli</groupId>
<artifactId>xxl-job-core</artifactId>
</dependency>
<dependency>
<groupId>com.yomahub</groupId>
<artifactId>tlog-xxljob-spring-boot-starter</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -1,33 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>ruoyi-vue-plus</artifactId>
<groupId>com.ruoyi</groupId>
<version>4.3.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ruoyi-oss</artifactId>
<description>
OSS对象存储模块
</description>
<dependencies>
<!-- 通用工具-->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-s3</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -1,40 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>ruoyi-vue-plus</artifactId>
<groupId>com.ruoyi</groupId>
<version>4.3.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ruoyi-sms</artifactId>
<description>
SMS短信模块
</description>
<dependencies>
<!-- 通用工具-->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>dysmsapi20170525</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.tencentcloudapi</groupId>
<artifactId>tencentcloud-sdk-java</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project>

View File

@ -1,45 +0,0 @@
package com.ruoyi.sms.config;
import com.ruoyi.sms.config.properties.SmsProperties;
import com.ruoyi.sms.core.AliyunSmsTemplate;
import com.ruoyi.sms.core.SmsTemplate;
import com.ruoyi.sms.core.TencentSmsTemplate;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 短信配置类
*
* @author Lion Li
* @version 4.2.0
*/
@Configuration
public class SmsConfig {
@Configuration
@ConditionalOnProperty(value = "sms.enabled", havingValue = "true")
@ConditionalOnClass(com.aliyun.dysmsapi20170525.Client.class)
static class AliyunSmsConfig {
@Bean
public SmsTemplate aliyunSmsTemplate(SmsProperties smsProperties) {
return new AliyunSmsTemplate(smsProperties);
}
}
@Configuration
@ConditionalOnProperty(value = "sms.enabled", havingValue = "true")
@ConditionalOnClass(com.tencentcloudapi.sms.v20190711.SmsClient.class)
static class TencentSmsConfig {
@Bean
public SmsTemplate tencentSmsTemplate(SmsProperties smsProperties) {
return new TencentSmsTemplate(smsProperties);
}
}
}

View File

@ -1,47 +0,0 @@
package com.ruoyi.sms.config.properties;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* SMS短信 配置属性
*
* @author Lion Li
* @version 4.2.0
*/
@Data
@Component
@ConfigurationProperties(prefix = "sms")
public class SmsProperties {
private Boolean enabled;
/**
* 配置节点
* 阿里云 dysmsapi.aliyuncs.com
* 腾讯云 sms.tencentcloudapi.com
*/
private String endpoint;
/**
* key
*/
private String accessKeyId;
/**
* 密匙
*/
private String accessKeySecret;
/*
* 短信签名
*/
private String signName;
/**
* 短信应用ID (腾讯专属)
*/
private String sdkAppId;
}

View File

@ -1,66 +0,0 @@
package com.ruoyi.sms.core;
import com.aliyun.dysmsapi20170525.Client;
import com.aliyun.dysmsapi20170525.models.SendSmsRequest;
import com.aliyun.dysmsapi20170525.models.SendSmsResponse;
import com.aliyun.teaopenapi.models.Config;
import com.ruoyi.common.utils.JsonUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.sms.config.properties.SmsProperties;
import com.ruoyi.sms.entity.SmsResult;
import com.ruoyi.sms.exception.SmsException;
import lombok.SneakyThrows;
import java.util.Map;
/**
* Aliyun 短信模板
*
* @author Lion Li
* @version 4.2.0
*/
public class AliyunSmsTemplate implements SmsTemplate {
private SmsProperties properties;
private Client client;
@SneakyThrows(Exception.class)
public AliyunSmsTemplate(SmsProperties smsProperties) {
this.properties = smsProperties;
Config config = new Config()
// 您的AccessKey ID
.setAccessKeyId(smsProperties.getAccessKeyId())
// 您的AccessKey Secret
.setAccessKeySecret(smsProperties.getAccessKeySecret())
// 访问的域名
.setEndpoint(smsProperties.getEndpoint());
this.client = new Client(config);
}
@Override
public SmsResult send(String phones, String templateId, Map<String, String> param) {
if (StringUtils.isBlank(phones)) {
throw new SmsException("手机号不能为空");
}
if (StringUtils.isBlank(templateId)) {
throw new SmsException("模板ID不能为空");
}
SendSmsRequest req = new SendSmsRequest()
.setPhoneNumbers(phones)
.setSignName(properties.getSignName())
.setTemplateCode(templateId)
.setTemplateParam(JsonUtils.toJsonString(param));
try {
SendSmsResponse resp = client.sendSms(req);
return SmsResult.builder()
.isSuccess("OK".equals(resp.getBody().getCode()))
.message(resp.getBody().getMessage())
.response(JsonUtils.toJsonString(resp))
.build();
} catch (Exception e) {
throw new SmsException(e.getMessage());
}
}
}

View File

@ -1,26 +0,0 @@
package com.ruoyi.sms.core;
import com.ruoyi.sms.entity.SmsResult;
import java.util.Map;
/**
* 短信模板
*
* @author Lion Li
* @version 4.2.0
*/
public interface SmsTemplate {
/**
* 发送短信
*
* @param phones 电话号(多个逗号分割)
* @param templateId 模板id
* @param param 模板对应参数
* 阿里 需使用 模板变量名称对应内容 例如: code=1234
* 腾讯 需使用 模板变量顺序对应内容 例如: 1=1234, 1为模板内第一个参数
*/
SmsResult send(String phones, String templateId, Map<String, String> param);
}

View File

@ -1,82 +0,0 @@
package com.ruoyi.sms.core;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ArrayUtil;
import com.ruoyi.common.utils.JsonUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.sms.config.properties.SmsProperties;
import com.ruoyi.sms.entity.SmsResult;
import com.ruoyi.sms.exception.SmsException;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.profile.ClientProfile;
import com.tencentcloudapi.common.profile.HttpProfile;
import com.tencentcloudapi.sms.v20190711.SmsClient;
import com.tencentcloudapi.sms.v20190711.models.SendSmsRequest;
import com.tencentcloudapi.sms.v20190711.models.SendSmsResponse;
import com.tencentcloudapi.sms.v20190711.models.SendStatus;
import lombok.SneakyThrows;
import java.util.Arrays;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
/**
* Tencent 短信模板
*
* @author Lion Li
* @version 4.2.0
*/
public class TencentSmsTemplate implements SmsTemplate {
private SmsProperties properties;
private SmsClient client;
@SneakyThrows(Exception.class)
public TencentSmsTemplate(SmsProperties smsProperties) {
this.properties = smsProperties;
Credential credential = new Credential(smsProperties.getAccessKeyId(), smsProperties.getAccessKeySecret());
HttpProfile httpProfile = new HttpProfile();
httpProfile.setEndpoint(smsProperties.getEndpoint());
ClientProfile clientProfile = new ClientProfile();
clientProfile.setHttpProfile(httpProfile);
this.client = new SmsClient(credential, "", clientProfile);
}
@Override
public SmsResult send(String phones, String templateId, Map<String, String> param) {
if (StringUtils.isBlank(phones)) {
throw new SmsException("手机号不能为空");
}
if (StringUtils.isBlank(templateId)) {
throw new SmsException("模板ID不能为空");
}
SendSmsRequest req = new SendSmsRequest();
Set<String> set = Arrays.stream(phones.split(",")).map(p -> "+86" + p).collect(Collectors.toSet());
req.setPhoneNumberSet(ArrayUtil.toArray(set, String.class));
if (CollUtil.isNotEmpty(param)) {
req.setTemplateParamSet(ArrayUtil.toArray(param.values(), String.class));
}
req.setTemplateID(templateId);
req.setSign(properties.getSignName());
req.setSmsSdkAppid(properties.getSdkAppId());
try {
SendSmsResponse resp = client.SendSms(req);
SmsResult.SmsResultBuilder builder = SmsResult.builder()
.isSuccess(true)
.message("send success")
.response(JsonUtils.toJsonString(resp));
for (SendStatus sendStatus : resp.getSendStatusSet()) {
if (!"Ok".equals(sendStatus.getCode())) {
builder.isSuccess(false).message(sendStatus.getMessage());
break;
}
}
return builder.build();
} catch (Exception e) {
throw new SmsException(e.getMessage());
}
}
}

View File

@ -1,31 +0,0 @@
package com.ruoyi.sms.entity;
import lombok.Builder;
import lombok.Data;
/**
* 上传返回体
*
* @author Lion Li
*/
@Data
@Builder
public class SmsResult {
/**
* 是否成功
*/
private boolean isSuccess;
/**
* 响应消息
*/
private String message;
/**
* 实际响应体
* <p>
* 可自行转换为 SDK 对应的 SendSmsResponse
*/
private String response;
}

View File

@ -1,16 +0,0 @@
package com.ruoyi.sms.exception;
/**
* Sms异常类
*
* @author Lion Li
*/
public class SmsException extends RuntimeException {
private static final long serialVersionUID = 1L;
public SmsException(String msg) {
super(msg);
}
}

View File

@ -1,40 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>ruoyi-vue-plus</artifactId>
<groupId>com.ruoyi</groupId>
<version>4.3.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ruoyi-system</artifactId>
<description>
system系统模块
</description>
<dependencies>
<!-- 通用工具-->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId>
</dependency>
<!-- OSS功能模块 -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-oss</artifactId>
</dependency>
<!-- SMS功能模块 -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-sms</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -1,3 +0,0 @@
java包使用 `.` 分割 resource 目录使用 `/` 分割
<br>
此文件目的 防止文件夹粘连找不到 `xml` 文件

View File

@ -0,0 +1,21 @@
# 告诉EditorConfig插件这是根文件不用继续往上查找
root = true
# 匹配全部文件
[*]
# 缩进风格可选space、tab
indent_style = space
# 缩进的空格数
indent_size = 2
# 设置字符集
charset = utf-8
# 结尾换行符可选lf、cr、crlf
end_of_line = lf
# 在文件结尾插入新行
trim_trailing_whitespace = true
# 删除一行中的前后空格
insert_final_newline = true
[*.md]
insert_final_newline = false
trim_trailing_whitespace = false

View File

@ -0,0 +1,17 @@
# 页面标题
VITE_APP_TITLE = RuoYi-Vue-Plus后台管理系统
# 开发环境配置
VITE_APP_ENV = 'development'
# 若依管理系统/开发环境
VITE_APP_BASE_API = '/dev-api'
# 应用访问路径 例如使用前缀 /admin/
VITE_APP_CONTEXT_PATH = '/'
# 监控地址
VITE_APP_MONITRO_ADMIN = 'http://localhost:9090/admin/applications'
# xxl-job 控制台地址
VITE_APP_XXL_JOB_ADMIN = 'http://localhost:9100/xxl-job-admin'

View File

@ -0,0 +1,20 @@
# 页面标题
VITE_APP_TITLE = RuoYi-Vue-Plus后台管理系统
# 生产环境配置
VITE_APP_ENV = 'production'
# 应用访问路径 例如使用前缀 /admin/
VITE_APP_CONTEXT_PATH = '/'
# 监控地址
VITE_APP_MONITRO_ADMIN = '/admin/applications'
# 监控地址
VITE_APP_XXL_JOB_ADMIN = '/xxl-job-admin'
# 若依管理系统/生产环境
VITE_APP_BASE_API = '/prod-api'
# 是否在打包时开启压缩,支持 gzip 和 brotli
VITE_BUILD_COMPRESS = gzip

23
ruoyi-ui-vue3/.gitignore vendored Normal file
View File

@ -0,0 +1,23 @@
.DS_Store
node_modules/
dist/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
**/*.log
tests/**/coverage/
tests/e2e/reports
selenium-debug.log
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.local
package-lock.json
yarn.lock

83
ruoyi-ui-vue3/README.md Normal file
View File

@ -0,0 +1,83 @@
## 平台简介
* 本仓库为前端技术栈 [Vue3](https://v3.cn.vuejs.org) + [Element Plus](https://element-plus.org/zh-CN) + [Vite](https://cn.vitejs.dev) 版本。
* 配套后端代码仓库地址[RuoYi-Vue-Plus 4.X(注意版本号)](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus)
* 5.X后端需要使用此项目 [plus-ui](https://gitee.com/JavaLionLi/plus-ui)
## 前端运行
```bash
# 进入项目目录
cd ruoyi-ui-vue3
# 安装依赖
npm install --registry=https://registry.npmmirror.com
# 启动服务
npm run dev
# 构建测试环境 yarn build:stage
# 构建生产环境 yarn build:prod
# 前端访问地址 http://localhost:80
```
## 后端改造
参考后端代码内 `ruoyi-generator/resources/vm/vue/v3/readme.txt` 说明
## 内置功能
1. 用户管理:用户是系统操作者,该功能主要完成系统用户配置。
2. 部门管理:配置系统组织机构(公司、部门、小组),树结构展现支持数据权限。
3. 岗位管理:配置系统用户所属担任职务。
4. 菜单管理:配置系统菜单,操作权限,按钮权限标识等。
5. 角色管理:角色菜单权限分配、设置角色按机构进行数据范围权限划分。
6. 字典管理:对系统中经常使用的一些较为固定的数据进行维护。
7. 参数管理:对系统动态配置常用参数。
8. 通知公告:系统通知公告信息发布维护。
9. 操作日志:系统正常操作日志记录和查询;系统异常信息日志记录和查询。
10. 登录日志:系统登录日志记录查询包含登录异常。
11. 在线用户:当前系统中活跃用户状态监控。
12. 定时任务:在线(添加、修改、删除)任务调度包含执行结果日志。
13. 代码生成前后端代码的生成java、html、xml、sql支持CRUD下载 。
14. 系统接口根据业务代码自动生成相关的api接口文档。
15. 服务监控监视当前系统CPU、内存、磁盘、堆栈等相关信息。
16. 缓存监控:对系统的缓存信息查询,命令统计等。
17. 在线构建器拖动表单元素生成相应的HTML代码。
18. 连接池监视监视当前系统数据库连接池状态可进行分析SQL找出系统性能瓶颈。
## 演示图
<table>
<tr>
<td><img src="https://oscimg.oschina.net/oscnet/cd1f90be5f2684f4560c9519c0f2a232ee8.jpg"/></td>
<td><img src="https://oscimg.oschina.net/oscnet/1cbcf0e6f257c7d3a063c0e3f2ff989e4b3.jpg"/></td>
</tr>
<tr>
<td><img src="https://oscimg.oschina.net/oscnet/up-8074972883b5ba0622e13246738ebba237a.png"/></td>
<td><img src="https://oscimg.oschina.net/oscnet/up-9f88719cdfca9af2e58b352a20e23d43b12.png"/></td>
</tr>
<tr>
<td><img src="https://oscimg.oschina.net/oscnet/up-39bf2584ec3a529b0d5a3b70d15c9b37646.png"/></td>
<td><img src="https://oscimg.oschina.net/oscnet/up-936ec82d1f4872e1bc980927654b6007307.png"/></td>
</tr>
<tr>
<td><img src="https://oscimg.oschina.net/oscnet/up-b2d62ceb95d2dd9b3fbe157bb70d26001e9.png"/></td>
<td><img src="https://oscimg.oschina.net/oscnet/up-d67451d308b7a79ad6819723396f7c3d77a.png"/></td>
</tr>
<tr>
<td><img src="https://oscimg.oschina.net/oscnet/5e8c387724954459291aafd5eb52b456f53.jpg"/></td>
<td><img src="https://oscimg.oschina.net/oscnet/644e78da53c2e92a95dfda4f76e6d117c4b.jpg"/></td>
</tr>
<tr>
<td><img src="https://oscimg.oschina.net/oscnet/up-8370a0d02977eebf6dbf854c8450293c937.png"/></td>
<td><img src="https://oscimg.oschina.net/oscnet/up-49003ed83f60f633e7153609a53a2b644f7.png"/></td>
</tr>
<tr>
<td><img src="https://oscimg.oschina.net/oscnet/up-d4fe726319ece268d4746602c39cffc0621.png"/></td>
<td><img src="https://oscimg.oschina.net/oscnet/up-c195234bbcd30be6927f037a6755e6ab69c.png"/></td>
</tr>
<tr>
<td><img src="https://oscimg.oschina.net/oscnet/b6115bc8c31de52951982e509930b20684a.jpg"/></td>
<td><img src="https://oscimg.oschina.net/oscnet/up-5e4daac0bb59612c5038448acbcef235e3a.png"/></td>
</tr>
</table>

View File

@ -0,0 +1,12 @@
@echo off
echo.
echo [<5B><>Ϣ] <20><><EFBFBD><EFBFBD>Web<65><62><EFBFBD>̣<EFBFBD><CCA3><EFBFBD><EFBFBD><EFBFBD>dist<73>ļ<EFBFBD><C4BC><EFBFBD>
echo.
%~d0
cd %~dp0
cd ..
yarn build:prod
pause

View File

@ -0,0 +1,12 @@
@echo off
echo.
echo [<5B><>Ϣ] <20><>װWeb<65><62><EFBFBD>̣<EFBFBD><CCA3><EFBFBD><EFBFBD><EFBFBD>node_modules<65>ļ<EFBFBD><C4BC><EFBFBD>
echo.
%~d0
cd %~dp0
cd ..
yarn --registry=https://registry.npmmirror.com
pause

View File

@ -0,0 +1,12 @@
@echo off
echo.
echo [<5B><>Ϣ] ʹ<><CAB9> Vite <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Web <20><><EFBFBD>̡<EFBFBD>
echo.
%~d0
cd %~dp0
cd ..
yarn dev
pause

File diff suppressed because one or more lines are too long

215
ruoyi-ui-vue3/index.html Normal file
View File

@ -0,0 +1,215 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="renderer" content="webkit">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<link rel="icon" href="/favicon.ico">
<title>RuoYi-Vue-Plus管理系统</title>
<!--[if lt IE 11]><script>window.location.href='/html/ie.html';</script><![endif]-->
<style>
html,
body,
#app {
height: 100%;
margin: 0px;
padding: 0px;
}
.chromeframe {
margin: 0.2em 0;
background: #ccc;
color: #000;
padding: 0.2em 0;
}
#loader-wrapper {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 999999;
}
#loader {
display: block;
position: relative;
left: 50%;
top: 50%;
width: 150px;
height: 150px;
margin: -75px 0 0 -75px;
border-radius: 50%;
border: 3px solid transparent;
border-top-color: #FFF;
-webkit-animation: spin 2s linear infinite;
-ms-animation: spin 2s linear infinite;
-moz-animation: spin 2s linear infinite;
-o-animation: spin 2s linear infinite;
animation: spin 2s linear infinite;
z-index: 1001;
}
#loader:before {
content: "";
position: absolute;
top: 5px;
left: 5px;
right: 5px;
bottom: 5px;
border-radius: 50%;
border: 3px solid transparent;
border-top-color: #FFF;
-webkit-animation: spin 3s linear infinite;
-moz-animation: spin 3s linear infinite;
-o-animation: spin 3s linear infinite;
-ms-animation: spin 3s linear infinite;
animation: spin 3s linear infinite;
}
#loader:after {
content: "";
position: absolute;
top: 15px;
left: 15px;
right: 15px;
bottom: 15px;
border-radius: 50%;
border: 3px solid transparent;
border-top-color: #FFF;
-moz-animation: spin 1.5s linear infinite;
-o-animation: spin 1.5s linear infinite;
-ms-animation: spin 1.5s linear infinite;
-webkit-animation: spin 1.5s linear infinite;
animation: spin 1.5s linear infinite;
}
@-webkit-keyframes spin {
0% {
-webkit-transform: rotate(0deg);
-ms-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
-ms-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@keyframes spin {
0% {
-webkit-transform: rotate(0deg);
-ms-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
-ms-transform: rotate(360deg);
transform: rotate(360deg);
}
}
#loader-wrapper .loader-section {
position: fixed;
top: 0;
width: 51%;
height: 100%;
background: #7171C6;
z-index: 1000;
-webkit-transform: translateX(0);
-ms-transform: translateX(0);
transform: translateX(0);
}
#loader-wrapper .loader-section.section-left {
left: 0;
}
#loader-wrapper .loader-section.section-right {
right: 0;
}
.loaded #loader-wrapper .loader-section.section-left {
-webkit-transform: translateX(-100%);
-ms-transform: translateX(-100%);
transform: translateX(-100%);
-webkit-transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000);
transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000);
}
.loaded #loader-wrapper .loader-section.section-right {
-webkit-transform: translateX(100%);
-ms-transform: translateX(100%);
transform: translateX(100%);
-webkit-transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000);
transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000);
}
.loaded #loader {
opacity: 0;
-webkit-transition: all 0.3s ease-out;
transition: all 0.3s ease-out;
}
.loaded #loader-wrapper {
visibility: hidden;
-webkit-transform: translateY(-100%);
-ms-transform: translateY(-100%);
transform: translateY(-100%);
-webkit-transition: all 0.3s 1s ease-out;
transition: all 0.3s 1s ease-out;
}
.no-js #loader-wrapper {
display: none;
}
.no-js h1 {
color: #222222;
}
#loader-wrapper .load_title {
font-family: 'Open Sans';
color: #FFF;
font-size: 19px;
width: 100%;
text-align: center;
z-index: 9999999999999;
position: absolute;
top: 60%;
opacity: 1;
line-height: 30px;
}
#loader-wrapper .load_title span {
font-weight: normal;
font-style: italic;
font-size: 13px;
color: #FFF;
opacity: 0.5;
}
</style>
</head>
<body>
<div id="app">
<div id="loader-wrapper">
<div id="loader"></div>
<div class="loader-section section-left"></div>
<div class="loader-section section-right"></div>
<div class="load_title">正在加载系统资源,请耐心等待</div>
</div>
</div>
<script type="module" src="/src/main.js"></script>
</body>
</html>

View File

@ -0,0 +1,43 @@
{
"name": "ruoyi-vue-plus",
"version": "4.8.2",
"description": "RuoYi-Vue-Plus后台管理系统",
"author": "LionLi",
"license": "MIT",
"scripts": {
"dev": "vite",
"build:prod": "vite build",
"preview": "vite preview"
},
"repository": {
"type": "git",
"url": "https://gitee.com/JavaLionLi/RuoYi-Vue-Plus-UI.git"
},
"dependencies": {
"@element-plus/icons-vue": "2.0.10",
"@vueup/vue-quill": "1.2.0",
"@vueuse/core": "9.5.0",
"axios": "0.27.2",
"echarts": "5.4.0",
"element-plus": "2.2.27",
"file-saver": "2.0.5",
"fuse.js": "6.6.2",
"js-cookie": "3.0.1",
"jsencrypt": "3.3.1",
"nprogress": "0.2.0",
"pinia": "2.0.22",
"vue": "3.2.45",
"vue-cropper": "1.0.3",
"vue-router": "4.1.4"
},
"devDependencies": {
"@vitejs/plugin-vue": "3.1.0",
"@vue/compiler-sfc": "3.2.45",
"sass": "1.56.1",
"unplugin-auto-import": "0.11.4",
"vite": "3.2.3",
"vite-plugin-compression": "0.5.1",
"vite-plugin-svg-icons": "2.0.1",
"unplugin-vue-setup-extend-plus": "0.4.9"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

15
ruoyi-ui-vue3/src/App.vue Normal file
View File

@ -0,0 +1,15 @@
<template>
<router-view />
</template>
<script setup>
import useSettingsStore from '@/store/modules/settings'
import { handleThemeStyle } from '@/utils/theme'
onMounted(() => {
nextTick(() => {
// 初始化主题样式
handleThemeStyle(useSettingsStore().theme)
})
})
</script>

View File

@ -0,0 +1,54 @@
import request from '@/utils/request'
// 查询测试单表列表
export function listDemo(query) {
return request({
url: '/demo/demo/list',
method: 'get',
params: query
})
}
// 自定义分页接口
export function pageDemo(query) {
return request({
url: '/demo/demo/page',
method: 'get',
params: query
})
}
// 查询测试单表详细
export function getDemo(id) {
return request({
url: '/demo/demo/' + id,
method: 'get'
})
}
// 新增测试单表
export function addDemo(data) {
return request({
url: '/demo/demo',
method: 'post',
data: data
})
}
// 修改测试单表
export function updateDemo(data) {
return request({
url: '/demo/demo',
method: 'put',
data: data
})
}
// 删除测试单表
export function delDemo(id) {
return request({
url: '/demo/demo/' + id,
method: 'delete'
})
}

View File

@ -0,0 +1,44 @@
import request from '@/utils/request'
// 查询测试树表列表
export function listTree(query) {
return request({
url: '/demo/tree/list',
method: 'get',
params: query
})
}
// 查询测试树表详细
export function getTree(id) {
return request({
url: '/demo/tree/' + id,
method: 'get'
})
}
// 新增测试树表
export function addTree(data) {
return request({
url: '/demo/tree',
method: 'post',
data: data
})
}
// 修改测试树表
export function updateTree(data) {
return request({
url: '/demo/tree',
method: 'put',
data: data
})
}
// 删除测试树表
export function delTree(id) {
return request({
url: '/demo/tree/' + id,
method: 'delete'
})
}

View File

@ -0,0 +1,59 @@
import request from '@/utils/request'
// 登录方法
export function login(username, password, code, uuid) {
const data = {
username,
password,
code,
uuid
}
return request({
url: '/login',
headers: {
isToken: false
},
method: 'post',
data: data
})
}
// 注册方法
export function register(data) {
return request({
url: '/register',
headers: {
isToken: false
},
method: 'post',
data: data
})
}
// 获取用户详细信息
export function getInfo() {
return request({
url: '/getInfo',
method: 'get'
})
}
// 退出方法
export function logout() {
return request({
url: '/logout',
method: 'post'
})
}
// 获取验证码
export function getCodeImg() {
return request({
url: '/captchaImage',
headers: {
isToken: false
},
method: 'get',
timeout: 20000
})
}

View File

@ -0,0 +1,9 @@
import request from '@/utils/request'
// 获取路由
export const getRouters = () => {
return request({
url: '/getRouters',
method: 'get'
})
}

View File

@ -0,0 +1,57 @@
import request from '@/utils/request'
// 查询缓存详细
export function getCache() {
return request({
url: '/monitor/cache',
method: 'get'
})
}
// 查询缓存名称列表
export function listCacheName() {
return request({
url: '/monitor/cache/getNames',
method: 'get'
})
}
// 查询缓存键名列表
export function listCacheKey(cacheName) {
return request({
url: '/monitor/cache/getKeys/' + cacheName,
method: 'get'
})
}
// 查询缓存内容
export function getCacheValue(cacheName, cacheKey) {
return request({
url: '/monitor/cache/getValue/' + cacheName + '/' + cacheKey,
method: 'get'
})
}
// 清理指定名称缓存
export function clearCacheName(cacheName) {
return request({
url: '/monitor/cache/clearCacheName/' + cacheName,
method: 'delete'
})
}
// 清理指定键名缓存
export function clearCacheKey(cacheName, cacheKey) {
return request({
url: '/monitor/cache/clearCacheKey/' + cacheName + '/' + cacheKey,
method: 'delete'
})
}
// 清理全部缓存
export function clearCacheAll() {
return request({
url: '/monitor/cache/clearCacheAll',
method: 'delete'
})
}

View File

@ -0,0 +1,34 @@
import request from '@/utils/request'
// 查询登录日志列表
export function list(query) {
return request({
url: '/monitor/logininfor/list',
method: 'get',
params: query
})
}
// 删除登录日志
export function delLogininfor(infoId) {
return request({
url: '/monitor/logininfor/' + infoId,
method: 'delete'
})
}
// 解锁用户登录状态
export function unlockLogininfor(userName) {
return request({
url: '/monitor/logininfor/unlock/' + userName,
method: 'get'
})
}
// 清空登录日志
export function cleanLogininfor() {
return request({
url: '/monitor/logininfor/clean',
method: 'delete'
})
}

View File

@ -0,0 +1,18 @@
import request from '@/utils/request'
// 查询在线用户列表
export function list(query) {
return request({
url: '/monitor/online/list',
method: 'get',
params: query
})
}
// 强退用户
export function forceLogout(tokenId) {
return request({
url: '/monitor/online/' + tokenId,
method: 'delete'
})
}

View File

@ -0,0 +1,26 @@
import request from '@/utils/request'
// 查询操作日志列表
export function list(query) {
return request({
url: '/monitor/operlog/list',
method: 'get',
params: query
})
}
// 删除操作日志
export function delOperlog(operId) {
return request({
url: '/monitor/operlog/' + operId,
method: 'delete'
})
}
// 清空操作日志
export function cleanOperlog() {
return request({
url: '/monitor/operlog/clean',
method: 'delete'
})
}

View File

@ -0,0 +1,72 @@
import request from '@/utils/request'
// 查询参数列表
export function listConfig(query) {
return request({
url: '/system/config/list',
method: 'get',
params: query
})
}
// 查询参数详细
export function getConfig(configId) {
return request({
url: '/system/config/' + configId,
method: 'get'
})
}
// 根据参数键名查询参数值
export function getConfigKey(configKey) {
return request({
url: '/system/config/configKey/' + configKey,
method: 'get'
})
}
// 新增参数配置
export function addConfig(data) {
return request({
url: '/system/config',
method: 'post',
data: data
})
}
// 修改参数配置
export function updateConfig(data) {
return request({
url: '/system/config',
method: 'put',
data: data
})
}
// 修改参数配置
export function updateConfigByKey(key, value) {
return request({
url: '/system/config/updateByKey',
method: 'put',
data: {
configKey: key,
configValue: value
}
})
}
// 删除参数配置
export function delConfig(configId) {
return request({
url: '/system/config/' + configId,
method: 'delete'
})
}
// 刷新参数缓存
export function refreshCache() {
return request({
url: '/system/config/refreshCache',
method: 'delete'
})
}

View File

@ -0,0 +1,52 @@
import request from '@/utils/request'
// 查询部门列表
export function listDept(query) {
return request({
url: '/system/dept/list',
method: 'get',
params: query
})
}
// 查询部门列表(排除节点)
export function listDeptExcludeChild(deptId) {
return request({
url: '/system/dept/list/exclude/' + deptId,
method: 'get'
})
}
// 查询部门详细
export function getDept(deptId) {
return request({
url: '/system/dept/' + deptId,
method: 'get'
})
}
// 新增部门
export function addDept(data) {
return request({
url: '/system/dept',
method: 'post',
data: data
})
}
// 修改部门
export function updateDept(data) {
return request({
url: '/system/dept',
method: 'put',
data: data
})
}
// 删除部门
export function delDept(deptId) {
return request({
url: '/system/dept/' + deptId,
method: 'delete'
})
}

View File

@ -0,0 +1,52 @@
import request from '@/utils/request'
// 查询字典数据列表
export function listData(query) {
return request({
url: '/system/dict/data/list',
method: 'get',
params: query
})
}
// 查询字典数据详细
export function getData(dictCode) {
return request({
url: '/system/dict/data/' + dictCode,
method: 'get'
})
}
// 根据字典类型查询字典数据信息
export function getDicts(dictType) {
return request({
url: '/system/dict/data/type/' + dictType,
method: 'get'
})
}
// 新增字典数据
export function addData(data) {
return request({
url: '/system/dict/data',
method: 'post',
data: data
})
}
// 修改字典数据
export function updateData(data) {
return request({
url: '/system/dict/data',
method: 'put',
data: data
})
}
// 删除字典数据
export function delData(dictCode) {
return request({
url: '/system/dict/data/' + dictCode,
method: 'delete'
})
}

View File

@ -0,0 +1,60 @@
import request from '@/utils/request'
// 查询字典类型列表
export function listType(query) {
return request({
url: '/system/dict/type/list',
method: 'get',
params: query
})
}
// 查询字典类型详细
export function getType(dictId) {
return request({
url: '/system/dict/type/' + dictId,
method: 'get'
})
}
// 新增字典类型
export function addType(data) {
return request({
url: '/system/dict/type',
method: 'post',
data: data
})
}
// 修改字典类型
export function updateType(data) {
return request({
url: '/system/dict/type',
method: 'put',
data: data
})
}
// 删除字典类型
export function delType(dictId) {
return request({
url: '/system/dict/type/' + dictId,
method: 'delete'
})
}
// 刷新字典缓存
export function refreshCache() {
return request({
url: '/system/dict/type/refreshCache',
method: 'delete'
})
}
// 获取字典选择框列表
export function optionselect() {
return request({
url: '/system/dict/type/optionselect',
method: 'get'
})
}

View File

@ -0,0 +1,60 @@
import request from '@/utils/request'
// 查询菜单列表
export function listMenu(query) {
return request({
url: '/system/menu/list',
method: 'get',
params: query
})
}
// 查询菜单详细
export function getMenu(menuId) {
return request({
url: '/system/menu/' + menuId,
method: 'get'
})
}
// 查询菜单下拉树结构
export function treeselect() {
return request({
url: '/system/menu/treeselect',
method: 'get'
})
}
// 根据角色ID查询菜单下拉树结构
export function roleMenuTreeselect(roleId) {
return request({
url: '/system/menu/roleMenuTreeselect/' + roleId,
method: 'get'
})
}
// 新增菜单
export function addMenu(data) {
return request({
url: '/system/menu',
method: 'post',
data: data
})
}
// 修改菜单
export function updateMenu(data) {
return request({
url: '/system/menu',
method: 'put',
data: data
})
}
// 删除菜单
export function delMenu(menuId) {
return request({
url: '/system/menu/' + menuId,
method: 'delete'
})
}

View File

@ -0,0 +1,44 @@
import request from '@/utils/request'
// 查询公告列表
export function listNotice(query) {
return request({
url: '/system/notice/list',
method: 'get',
params: query
})
}
// 查询公告详细
export function getNotice(noticeId) {
return request({
url: '/system/notice/' + noticeId,
method: 'get'
})
}
// 新增公告
export function addNotice(data) {
return request({
url: '/system/notice',
method: 'post',
data: data
})
}
// 修改公告
export function updateNotice(data) {
return request({
url: '/system/notice',
method: 'put',
data: data
})
}
// 删除公告
export function delNotice(noticeId) {
return request({
url: '/system/notice/' + noticeId,
method: 'delete'
})
}

View File

@ -0,0 +1,27 @@
import request from '@/utils/request'
// 查询OSS对象存储列表
export function listOss(query) {
return request({
url: '/system/oss/list',
method: 'get',
params: query
})
}
// 查询OSS对象基于id串
export function listByIds(ossId) {
return request({
url: '/system/oss/listByIds/' + ossId,
method: 'get'
})
}
// 删除OSS对象存储
export function delOss(ossId) {
return request({
url: '/system/oss/' + ossId,
method: 'delete'
})
}

View File

@ -0,0 +1,58 @@
import request from '@/utils/request'
// 查询对象存储配置列表
export function listOssConfig(query) {
return request({
url: '/system/oss/config/list',
method: 'get',
params: query
})
}
// 查询对象存储配置详细
export function getOssConfig(ossConfigId) {
return request({
url: '/system/oss/config/' + ossConfigId,
method: 'get'
})
}
// 新增对象存储配置
export function addOssConfig(data) {
return request({
url: '/system/oss/config',
method: 'post',
data: data
})
}
// 修改对象存储配置
export function updateOssConfig(data) {
return request({
url: '/system/oss/config',
method: 'put',
data: data
})
}
// 删除对象存储配置
export function delOssConfig(ossConfigId) {
return request({
url: '/system/oss/config/' + ossConfigId,
method: 'delete'
})
}
// 对象存储状态修改
export function changeOssConfigStatus(ossConfigId, status, configKey) {
const data = {
ossConfigId,
status,
configKey
}
return request({
url: '/system/oss/config/changeStatus',
method: 'put',
data: data
})
}

View File

@ -0,0 +1,44 @@
import request from '@/utils/request'
// 查询岗位列表
export function listPost(query) {
return request({
url: '/system/post/list',
method: 'get',
params: query
})
}
// 查询岗位详细
export function getPost(postId) {
return request({
url: '/system/post/' + postId,
method: 'get'
})
}
// 新增岗位
export function addPost(data) {
return request({
url: '/system/post',
method: 'post',
data: data
})
}
// 修改岗位
export function updatePost(data) {
return request({
url: '/system/post',
method: 'put',
data: data
})
}
// 删除岗位
export function delPost(postId) {
return request({
url: '/system/post/' + postId,
method: 'delete'
})
}

View File

@ -0,0 +1,119 @@
import request from '@/utils/request'
// 查询角色列表
export function listRole(query) {
return request({
url: '/system/role/list',
method: 'get',
params: query
})
}
// 查询角色详细
export function getRole(roleId) {
return request({
url: '/system/role/' + roleId,
method: 'get'
})
}
// 新增角色
export function addRole(data) {
return request({
url: '/system/role',
method: 'post',
data: data
})
}
// 修改角色
export function updateRole(data) {
return request({
url: '/system/role',
method: 'put',
data: data
})
}
// 角色数据权限
export function dataScope(data) {
return request({
url: '/system/role/dataScope',
method: 'put',
data: data
})
}
// 角色状态修改
export function changeRoleStatus(roleId, status) {
const data = {
roleId,
status
}
return request({
url: '/system/role/changeStatus',
method: 'put',
data: data
})
}
// 删除角色
export function delRole(roleId) {
return request({
url: '/system/role/' + roleId,
method: 'delete'
})
}
// 查询角色已授权用户列表
export function allocatedUserList(query) {
return request({
url: '/system/role/authUser/allocatedList',
method: 'get',
params: query
})
}
// 查询角色未授权用户列表
export function unallocatedUserList(query) {
return request({
url: '/system/role/authUser/unallocatedList',
method: 'get',
params: query
})
}
// 取消用户授权角色
export function authUserCancel(data) {
return request({
url: '/system/role/authUser/cancel',
method: 'put',
data: data
})
}
// 批量取消用户授权角色
export function authUserCancelAll(data) {
return request({
url: '/system/role/authUser/cancelAll',
method: 'put',
params: data
})
}
// 授权用户选择
export function authUserSelectAll(data) {
return request({
url: '/system/role/authUser/selectAll',
method: 'put',
params: data
})
}
// 根据角色ID查询部门树结构
export function deptTreeSelect(roleId) {
return request({
url: '/system/role/deptTree/' + roleId,
method: 'get'
})
}

View File

@ -0,0 +1,135 @@
import request from '@/utils/request'
import { parseStrEmpty } from "@/utils/ruoyi";
// 查询用户列表
export function listUser(query) {
return request({
url: '/system/user/list',
method: 'get',
params: query
})
}
// 查询用户详细
export function getUser(userId) {
return request({
url: '/system/user/' + parseStrEmpty(userId),
method: 'get'
})
}
// 新增用户
export function addUser(data) {
return request({
url: '/system/user',
method: 'post',
data: data
})
}
// 修改用户
export function updateUser(data) {
return request({
url: '/system/user',
method: 'put',
data: data
})
}
// 删除用户
export function delUser(userId) {
return request({
url: '/system/user/' + userId,
method: 'delete'
})
}
// 用户密码重置
export function resetUserPwd(userId, password) {
const data = {
userId,
password
}
return request({
url: '/system/user/resetPwd',
method: 'put',
data: data
})
}
// 用户状态修改
export function changeUserStatus(userId, status) {
const data = {
userId,
status
}
return request({
url: '/system/user/changeStatus',
method: 'put',
data: data
})
}
// 查询用户个人信息
export function getUserProfile() {
return request({
url: '/system/user/profile',
method: 'get'
})
}
// 修改用户个人信息
export function updateUserProfile(data) {
return request({
url: '/system/user/profile',
method: 'put',
data: data
})
}
// 用户密码重置
export function updateUserPwd(oldPassword, newPassword) {
const data = {
oldPassword,
newPassword
}
return request({
url: '/system/user/profile/updatePwd',
method: 'put',
params: data
})
}
// 用户头像上传
export function uploadAvatar(data) {
return request({
url: '/system/user/profile/avatar',
method: 'post',
data: data
})
}
// 查询授权角色
export function getAuthRole(userId) {
return request({
url: '/system/user/authRole/' + userId,
method: 'get'
})
}
// 保存授权角色
export function updateAuthRole(data) {
return request({
url: '/system/user/authRole',
method: 'put',
params: data
})
}
// 查询部门下拉树结构
export function deptTreeSelect() {
return request({
url: '/system/user/deptTree',
method: 'get'
})
}

View File

@ -0,0 +1,85 @@
import request from '@/utils/request'
// 查询生成表数据
export function listTable(query) {
return request({
headers: { 'datasource': localStorage.getItem("dataName") },
url: '/tool/gen/list',
method: 'get',
params: query
})
}
// 查询db数据库列表
export function listDbTable(query) {
return request({
headers: { 'datasource': localStorage.getItem("dataName") },
url: '/tool/gen/db/list',
method: 'get',
params: query
})
}
// 查询表详细信息
export function getGenTable(tableId) {
return request({
headers: { 'datasource': localStorage.getItem("dataName") },
url: '/tool/gen/' + tableId,
method: 'get'
})
}
// 修改代码生成信息
export function updateGenTable(data) {
return request({
headers: { 'datasource': localStorage.getItem("dataName") },
url: '/tool/gen',
method: 'put',
data: data
})
}
// 导入表
export function importTable(data) {
return request({
headers: { 'datasource': localStorage.getItem("dataName") },
url: '/tool/gen/importTable',
method: 'post',
params: data
})
}
// 预览生成代码
export function previewTable(tableId) {
return request({
headers: { 'datasource': localStorage.getItem("dataName") },
url: '/tool/gen/preview/' + tableId,
method: 'get'
})
}
// 删除表数据
export function delTable(tableId) {
return request({
headers: { 'datasource': localStorage.getItem("dataName") },
url: '/tool/gen/' + tableId,
method: 'delete'
})
}
// 生成代码(自定义路径)
export function genCode(tableName) {
return request({
headers: { 'datasource': localStorage.getItem("dataName") },
url: '/tool/gen/genCode/' + tableName,
method: 'get'
})
}
// 同步数据库
export function synchDb(tableName) {
return request({
headers: { 'datasource': localStorage.getItem("dataName") },
url: '/tool/gen/synchDb/' + tableName,
method: 'get'
})
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

@ -0,0 +1 @@
<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M121.718 73.272v9.953c3.957-7.584 6.199-16.05 6.199-24.995C127.917 26.079 99.273 0 63.958 0 28.644 0 0 26.079 0 58.23c0 .403.028.806.028 1.21l22.97-25.953h13.34l-19.76 27.187h6.42V53.77l13.728-19.477v49.361H22.998V73.272H2.158c5.951 20.284 23.608 36.208 45.998 41.399-1.44 3.3-5.618 11.263-12.565 12.674-8.607 1.764 23.358.428 46.163-13.178 17.519-4.611 31.938-15.849 39.77-30.513h-13.506V73.272H85.02V59.464l22.998-25.977h13.008l-19.429 27.187h6.421v-7.433l13.727-19.402v39.433h-.027zm-78.24 2.822a10.516 10.516 0 0 1-.996-4.535V44.548c0-1.613.332-3.124.996-4.535a11.66 11.66 0 0 1 2.713-3.68c1.134-1.032 2.49-1.864 4.04-2.468 1.55-.605 3.21-.908 4.982-.908h11.292c1.77 0 3.431.303 4.981.908 1.522.604 2.85 1.41 3.986 2.418l-12.26 16.303v-2.898a1.96 1.96 0 0 0-.665-1.512c-.443-.403-.996-.604-1.66-.604-.665 0-1.218.201-1.661.604a1.96 1.96 0 0 0-.664 1.512v9.071L44.364 77.606a10.556 10.556 0 0 1-.886-1.512zm35.73-4.535c0 1.613-.332 3.124-.997 4.535a11.66 11.66 0 0 1-2.712 3.68c-1.134 1.032-2.49 1.864-4.04 2.469-1.55.604-3.21.907-4.982.907H55.185c-1.77 0-3.431-.303-4.981-.907-1.55-.605-2.906-1.437-4.041-2.47a12.49 12.49 0 0 1-1.384-1.512l13.727-18.217v6.375c0 .605.222 1.109.665 1.512.442.403.996.604 1.66.604.664 0 1.218-.201 1.66-.604a1.96 1.96 0 0 0 .665-1.512V53.87L75.97 36.838c.913.932 1.66 1.99 2.214 3.175.664 1.41.996 2.922.996 4.535v27.011h.028z"/></svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -0,0 +1 @@
<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M127.88 73.143c0 1.412-.506 2.635-1.518 3.669-1.011 1.033-2.209 1.55-3.592 1.55h-17.887c0 9.296-1.783 17.178-5.35 23.645l16.609 17.044c1.011 1.034 1.517 2.257 1.517 3.67 0 1.412-.506 2.635-1.517 3.668-.958 1.033-2.155 1.55-3.593 1.55-1.438 0-2.635-.517-3.593-1.55l-15.811-16.063a15.49 15.49 0 0 1-1.196 1.06c-.532.434-1.65 1.208-3.353 2.322a50.104 50.104 0 0 1-5.192 2.974c-1.758.87-3.94 1.658-6.546 2.364-2.607.706-5.189 1.06-7.748 1.06V47.044H58.89v73.062c-2.716 0-5.417-.367-8.106-1.102-2.688-.734-5.003-1.631-6.945-2.692a66.769 66.769 0 0 1-5.268-3.179c-1.571-1.057-2.73-1.94-3.476-2.65L33.9 109.34l-14.611 16.877c-1.066 1.14-2.344 1.711-3.833 1.711-1.277 0-2.422-.434-3.434-1.304-1.012-.978-1.557-2.187-1.635-3.627-.079-1.44.333-2.705 1.236-3.794l16.129-18.51c-3.087-6.197-4.63-13.644-4.63-22.342H5.235c-1.383 0-2.58-.517-3.592-1.55S.125 74.545.125 73.132c0-1.412.506-2.635 1.518-3.668 1.012-1.034 2.21-1.55 3.592-1.55h17.887V43.939L9.308 29.833c-1.012-1.033-1.517-2.256-1.517-3.669 0-1.412.505-2.635 1.517-3.668 1.012-1.034 2.21-1.55 3.593-1.55s2.58.516 3.593 1.55l13.813 14.106h67.396l13.814-14.106c1.012-1.034 2.21-1.55 3.592-1.55 1.384 0 2.581.516 3.593 1.55 1.012 1.033 1.518 2.256 1.518 3.668 0 1.413-.506 2.636-1.518 3.67l-13.814 14.105v23.975h17.887c1.383 0 2.58.516 3.593 1.55 1.011 1.033 1.517 2.256 1.517 3.668l-.005.01zM89.552 26.175H38.448c0-7.23 2.489-13.386 7.466-18.469C50.892 2.623 56.92.082 64 .082c7.08 0 13.108 2.541 18.086 7.624 4.977 5.083 7.466 11.24 7.466 18.469z"/></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1568899741379" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2054" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M960 591.424V368.96c0-0.288 0.16-0.512 0.16-0.768S960 367.68 960 367.424V192a32 32 0 0 0-32-32H96a32 32 0 0 0-32 32v175.424c0 0.288-0.16 0.512-0.16 0.768s0.16 0.48 0.16 0.768v222.464c0 0.288-0.16 0.512-0.16 0.768s0.16 0.48 0.16 0.768V864a32 32 0 0 0 32 32h832a32 32 0 0 0 32-32v-271.04c0-0.288 0.16-0.512 0.16-0.768S960 591.68 960 591.424z m-560-31.232v-160H608v160h-208z m208 64V832h-208v-207.808H608z m-480-224h208v160H128v-160z m544 0h224v160h-224v-160zM896 224v112.192H128V224h768zM128 624.192h208V832H128v-207.808zM672 832v-207.808h224V832h-224z" p-id="2055"></path></svg>

After

Width:  |  Height:  |  Size: 954 B

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1588670460195" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1314" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M230.4 307.712c13.824 0 25.088-11.264 25.088-25.088 0-100.352 81.92-182.272 182.272-182.272s182.272 81.408 182.272 182.272c0 13.824 11.264 25.088 25.088 25.088s25.088-11.264 24.576-25.088c0-127.488-103.936-231.936-231.936-231.936S205.824 154.624 205.824 282.624c-0.512 14.336 10.752 25.088 24.576 25.088z m564.736 234.496c-11.264 0-21.504 2.048-31.232 6.144 0-44.544-40.448-81.92-88.064-81.92-14.848 0-28.16 3.584-39.936 10.24-13.824-28.16-44.544-48.128-78.848-48.128-12.288 0-24.576 2.56-35.328 7.68V284.16c0-45.568-37.888-81.92-84.48-81.92s-84.48 36.864-84.48 81.92v348.672l-69.12-112.64c-18.432-28.16-58.368-36.864-91.136-19.968-26.624 14.336-46.592 47.104-30.208 88.064 3.072 8.192 76.8 205.312 171.52 311.296 0 0 28.16 24.576 43.008 58.88 4.096 9.728 13.312 15.36 22.528 15.36 3.072 0 6.656-0.512 9.728-2.048 12.288-5.12 18.432-19.968 12.8-32.256-19.456-44.544-53.76-74.752-53.76-74.752C281.6 768 209.408 573.44 208.384 570.88c-5.12-12.8-2.56-20.992 7.168-26.112 9.216-4.608 21.504-4.608 26.112 2.56l113.152 184.32c4.096 8.704 12.8 14.336 22.528 14.336 13.824 0 25.088-10.752 25.088-25.088V284.16c0-17.92 15.36-32.256 34.816-32.256s34.816 14.336 34.816 32.256v284.16c0 13.824 10.24 25.088 24.576 25.088 13.824 0 25.088-11.264 25.088-25.088v-57.344c0-17.92 15.36-32.768 34.816-32.768 19.968 0 37.376 15.36 37.376 32.768v95.232c0 7.168 3.072 13.312 7.68 17.92 4.608 4.608 10.752 7.168 17.92 7.168 13.824 0 24.576-11.264 24.576-25.088V547.84c0-18.432 13.824-32.256 32.256-32.256 20.48 0 38.912 15.36 38.912 32.256v95.232c0 13.824 11.264 25.088 25.088 25.088s24.576-11.264 25.088-25.088v-18.944c0-18.944 12.8-32.256 30.72-32.256 18.432 0 22.528 18.944 22.528 31.744 0 1.024-11.776 99.84-50.688 173.056-30.72 58.368-45.056 112.128-51.2 146.944-2.56 13.312 6.656 26.112 19.968 28.672 1.536 0 3.072 0.512 4.608 0.512 11.776 0 22.016-8.192 24.064-20.48 5.632-31.232 18.432-79.36 46.08-132.608 43.52-81.92 55.808-186.88 56.32-193.536-0.512-50.688-29.696-83.968-72.704-83.968z"></path></path></svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1576153230908" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="971" xmlns:xlink="http://www.w3.org/1999/xlink" width="81" height="81"><defs><style type="text/css"></style></defs><path d="M772.87036133 734.06115723c-43.34106445 0-80.00793458 27.93273926-93.76831055 66.57714843H475.90991211c-56.60705567 0-102.66723633-46.06018067-102.66723633-102.66723633V600.82446289h305.859375c13.76037598 38.64440918 50.42724609 66.57714844 93.76831055 66.57714844 55.12390137 0 99.94812012-44.82421875 99.94812012-99.94812012S827.9942627 467.50537109 772.87036133 467.50537109c-43.34106445 0-80.00793458 27.93273926-93.76831055 66.57714844H373.24267578V401.01062011h321.92687989c55.12390137 0 99.94812012-44.82421875 99.94812011-99.94812011V190.07312011C795.11767578 134.94921875 750.29345703 90.125 695.16955567 90.125H251.12963867C196.0057373 90.125 151.18151855 134.94921875 151.18151855 190.07312011V301.0625c0 55.12390137 44.82421875 99.94812012 99.94812012 99.94812012h55.53588867v296.96044921c0 93.35632325 75.97045898 169.32678223 169.32678224 169.32678223h203.19213866c13.76037598 38.64440918 50.42724609 66.57714844 93.76831055 66.57714844 55.12390137 0 99.94812012-44.82421875 99.94812012-99.94812012s-44.90661622-99.86572266-100.03051758-99.86572265z m0-199.89624024c18.37463379 0 33.28857422 14.91394043 33.28857422 33.28857423s-14.91394043 33.28857422-33.28857422 33.28857421-33.28857422-14.91394043-33.28857422-33.28857421 14.91394043-33.28857422 33.28857422-33.28857422zM217.75866699 301.0625V190.07312011c0-18.37463379 14.91394043-33.28857422 33.28857423-33.28857421h444.03991698c18.37463379 0 33.28857422 14.91394043 33.28857422 33.28857422V301.0625c0 18.37463379-14.91394043 33.28857422-33.28857422 33.28857422H251.12963867c-18.37463379 0-33.37097168-14.91394043-33.37097168-33.28857422z m555.11169434 566.23535156c-18.37463379 0-33.28857422-14.91394043-33.28857422-33.28857422 0-18.37463379 14.91394043-33.28857422 33.28857422-33.28857422s33.28857422 14.91394043 33.28857422 33.28857422c0.08239747 18.29223633-14.91394043 33.28857422-33.28857422 33.28857422z" p-id="972"></path></svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -0,0 +1 @@
<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M0 54.857h36.571V128H0V54.857zM91.429 27.43H128V128H91.429V27.429zM45.714 0h36.572v128H45.714V0z"/></svg>

After

Width:  |  Height:  |  Size: 179 B

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1575982282951" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="902" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M828.40625 90.125H195.59375C137.375 90.125 90.125 137.375 90.125 195.59375v632.8125c0 58.21875 47.25 105.46875 105.46875 105.46875h632.8125c58.21875 0 105.46875-47.25 105.46875-105.46875V195.59375c0-58.21875-47.25-105.46875-105.46875-105.46875z m52.734375 738.28125c0 29.16-23.57015625 52.734375-52.734375 52.734375H195.59375c-29.109375 0-52.734375-23.574375-52.734375-52.734375V195.59375c0-29.109375 23.625-52.734375 52.734375-52.734375h632.8125c29.16 0 52.734375 23.625 52.734375 52.734375v632.8125z" p-id="903"></path><path d="M421.52890625 709.55984375a36.28125 36.28125 0 0 1-27.55265625-12.66890625L205.17453125 476.613125a36.28546875 36.28546875 0 0 1 55.10109375-47.22890625l164.986875 192.4846875 342.16171875-298.48078125a36.2896875 36.2896875 0 0 1 47.70984375 54.68765625L445.3859375 700.6203125a36.3234375 36.3234375 0 0 1-23.85703125 8.93953125z" p-id="904"></path></svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

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