From 007a6d0c88755676465de81c477c416609fe04f6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90li?=
<15040126243@163.com>
Date: Mon, 12 Jul 2021 11:36:37 +0800
Subject: [PATCH] =?UTF-8?q?=E5=8F=91=E5=B8=83=20v2.5.0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
README.md | 26 +-
docker/deploy.sh | 92 +++++
docker/docker-compose.yml | 119 ++++++
docker/nginx/nginx.conf | 77 ++++
pom.xml | 280 +++++++++++++
ruoyi-extend/pom.xml | 18 +
ruoyi-extend/ruoyi-monitor-admin/Dockerfile | 13 +
ruoyi-extend/ruoyi-monitor-admin/pom.xml | 73 ++++
.../admin/MonitorAdminApplication.java | 19 +
.../admin/config/AdminServerConfig.java | 31 ++
.../monitor/admin/config/SecurityConfig.java | 48 +++
.../src/main/resources/application.yml | 11 +
ruoyi-ui/.env.development | 3 +
ruoyi-ui/.env.production | 3 +
ruoyi-ui/.env.staging | 3 +
ruoyi-ui/package.json | 2 +-
ruoyi-ui/src/api/system/role.js | 48 ++-
ruoyi-ui/src/api/system/user.js | 17 +
ruoyi-ui/src/assets/styles/ruoyi.scss | 18 +
ruoyi-ui/src/components/Editor/index.vue | 13 +-
ruoyi-ui/src/components/FileUpload/index.vue | 377 +++++++++---------
.../src/components/HeaderSearch/index.vue | 4 +-
ruoyi-ui/src/components/ImageUpload/index.vue | 310 +++++++++-----
ruoyi-ui/src/components/TopNav/index.vue | 4 +-
ruoyi-ui/src/directive/dialog/drag.js | 64 +++
ruoyi-ui/src/directive/index.js | 18 +
ruoyi-ui/src/directive/permission/hasPermi.js | 4 +-
ruoyi-ui/src/directive/permission/hasRole.js | 4 +-
ruoyi-ui/src/layout/components/AppMain.vue | 2 +-
.../src/layout/components/InnerLink/index.vue | 27 ++
ruoyi-ui/src/main.js | 13 +-
ruoyi-ui/src/router/index.js | 27 ++
ruoyi-ui/src/store/modules/permission.js | 3 +
ruoyi-ui/src/views/demo/demo/index.vue | 6 +-
ruoyi-ui/src/views/demo/tree/index.vue | 6 +-
ruoyi-ui/src/views/index.vue | 26 ++
ruoyi-ui/src/views/monitor/admin/index.vue | 20 +-
ruoyi-ui/src/views/system/notice/index.vue | 4 -
ruoyi-ui/src/views/system/role/authUser.vue | 213 ++++++++++
ruoyi-ui/src/views/system/role/index.vue | 38 +-
ruoyi-ui/src/views/system/role/selectUser.vue | 142 +++++++
ruoyi-ui/src/views/system/user/authRole.vue | 117 ++++++
ruoyi-ui/src/views/system/user/index.vue | 39 +-
ruoyi/Dockerfile | 14 +
ruoyi/pom.xml | 193 ++-------
.../ruoyi/common/constant/UserConstants.java | 5 +-
.../common/core/domain/entity/SysUser.java | 4 +
.../cache/MybatisPlusRedisCache.java | 3 +
.../core/mybatisplus/methods/InsertAll.java | 31 +-
.../ruoyi/common/core/redis/RedisCache.java | 6 +-
.../com/ruoyi/common/utils/DictUtils.java | 4 +-
.../com/ruoyi/common/utils/StringUtils.java | 28 ++
.../com/ruoyi/common/utils/poi/ExcelUtil.java | 62 +--
.../demo/controller/RedisCacheController.java | 70 ++++
.../feign/fallback/FeignTestFallback.java | 3 +
.../framework/config/AdminServerConfig.java | 63 ---
.../ruoyi/framework/config/FeignConfig.java | 36 ++
.../ruoyi/framework/config/RedisConfig.java | 8 +-
.../framework/config/SecurityConfig.java | 12 +-
.../config/properties/RedissonProperties.java | 34 +-
.../CreateAndUpdateMetaObjectHandler.java | 41 +-
.../service/GenTableServiceImpl.java | 12 +-
.../com/ruoyi/system/domain/vo/MetaVo.java | 24 +-
.../ruoyi/system/mapper/SysUserMapper.java | 16 +
.../ruoyi/system/service/ISysRoleService.java | 38 +-
.../ruoyi/system/service/ISysUserService.java | 30 +-
.../service/impl/SysMenuServiceImpl.java | 38 +-
.../service/impl/SysRoleServiceImpl.java | 68 ++++
.../service/impl/SysUserServiceImpl.java | 67 +++-
.../controller/system/SysIndexController.java | 29 ++
.../controller/system/SysMenuController.java | 9 +-
.../controller/system/SysRoleController.java | 57 ++-
.../controller/system/SysUserController.java | 27 ++
ruoyi/src/main/resources/application-dev.yml | 27 ++
ruoyi/src/main/resources/application-prod.yml | 31 +-
ruoyi/src/main/resources/application.yml | 55 ++-
.../resources/i18n/messages_en_US.properties | 33 ++
.../resources/i18n/messages_zh_CN.properties | 36 ++
.../resources/mapper/system/SysUserMapper.xml | 45 ++-
.../src/main/resources/vm/java/mapper.java.vm | 2 -
.../main/resources/vm/vue/index-tree.vue.vm | 46 +--
ruoyi/src/main/resources/vm/vue/index.vue.vm | 48 +--
82 files changed, 2952 insertions(+), 785 deletions(-)
create mode 100644 docker/deploy.sh
create mode 100644 docker/docker-compose.yml
create mode 100644 docker/nginx/nginx.conf
create mode 100644 pom.xml
create mode 100644 ruoyi-extend/pom.xml
create mode 100644 ruoyi-extend/ruoyi-monitor-admin/Dockerfile
create mode 100644 ruoyi-extend/ruoyi-monitor-admin/pom.xml
create mode 100644 ruoyi-extend/ruoyi-monitor-admin/src/main/java/com/ruoyi/monitor/admin/MonitorAdminApplication.java
create mode 100644 ruoyi-extend/ruoyi-monitor-admin/src/main/java/com/ruoyi/monitor/admin/config/AdminServerConfig.java
create mode 100644 ruoyi-extend/ruoyi-monitor-admin/src/main/java/com/ruoyi/monitor/admin/config/SecurityConfig.java
create mode 100644 ruoyi-extend/ruoyi-monitor-admin/src/main/resources/application.yml
create mode 100644 ruoyi-ui/src/directive/dialog/drag.js
create mode 100644 ruoyi-ui/src/directive/index.js
create mode 100644 ruoyi-ui/src/layout/components/InnerLink/index.vue
create mode 100644 ruoyi-ui/src/views/system/role/authUser.vue
create mode 100644 ruoyi-ui/src/views/system/role/selectUser.vue
create mode 100644 ruoyi-ui/src/views/system/user/authRole.vue
create mode 100644 ruoyi/Dockerfile
create mode 100644 ruoyi/src/main/java/com/ruoyi/common/utils/StringUtils.java
create mode 100644 ruoyi/src/main/java/com/ruoyi/demo/controller/RedisCacheController.java
delete mode 100644 ruoyi/src/main/java/com/ruoyi/framework/config/AdminServerConfig.java
create mode 100644 ruoyi/src/main/java/com/ruoyi/web/controller/system/SysIndexController.java
create mode 100644 ruoyi/src/main/resources/i18n/messages_en_US.properties
create mode 100644 ruoyi/src/main/resources/i18n/messages_zh_CN.properties
diff --git a/README.md b/README.md
index 688da088b..a56dc6c4a 100644
--- a/README.md
+++ b/README.md
@@ -4,12 +4,17 @@
[](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/blob/master/LICENSE)
[](https://www.jetbrains.com/?from=RuoYi-Vue-Plus)
-[](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus)
+[](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus)
[]()
[]()
[]()
-基于 RuoYi-Vue 集成 Mybatis-Plus Lombok Hutool 等便捷开发工具 适配重写相关业务 便于开发 定期与 RuoYi-Vue 同步
+RuoYi-Vue-Plus 是基于 RuoYi-Vue 针对 `分布式集群` 场景升级 定期与 RuoYi-Vue 同步
+
+集成 Lock4j dynamic-datasource 等分布式场景解决方案
+
+集成 Mybatis-Plus Lombok Hutool 等便捷开发工具 适配重写相关业务 便于开发
+
* 前端开发框架 Vue、Element UI
* 后端开发框架 Spring Boot、Redis
* 容器框架 Undertow 基于 Netty 的高性能容器
@@ -27,6 +32,7 @@
* 多数据源框架 dynamic-datasource 支持主从与多种类数据库异构
* Redis客户端 采用 Redisson 性能更强
* 分布式锁 Lock4j 注解锁、工具锁 多种多样
+* 部署方式 Docker 容器编排 一键部署业务集群
## 参考文档
@@ -34,6 +40,8 @@
>[初始化项目 必看](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/关于初始化项目?sort_id=4164117)
>
+>[部署项目 必看](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/关于应用部署?sort_id=4219382)
+>
>[参考文档 Wiki](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/pages)
## 提问四部曲
@@ -58,6 +66,12 @@
### 四、加群
以上三点已经能解决大家绝大部分问题了,如果还有问题没能通过这几种方式解决,那么加群,大家一起在群里探讨一下
+## 贡献代码
+
+欢迎各路英雄豪杰 `PR` 代码 请提交到 `dev` 开发分支 统一测试发版
+
+框架定位为 `通用后台管理系统(分布式集群强化)` 原则上不接受业务 `PR`
+
## 修改RuoYi功能
### 依赖改动
@@ -74,6 +88,7 @@
* 移除 fastjson 统一使用 jackson 序列化
* 集成 dynamic-datasource 多数据源(默认支持MySQL,其他种类需自行适配)
* 集成 Lock4j 实现分布式 注解锁、工具锁 多种多样
+* 增加 Docker 容器编排 打包插件与部署脚本
### 代码改动
@@ -90,14 +105,13 @@
### 其他
-* 同步升级 RuoYi-Vue 3.5.0
+* 同步升级 RuoYi-Vue
* GitHub 地址 [RuoYi-Vue-Plus-github](https://github.com/JavaLionLi/RuoYi-Vue-Plus)
* 单模块 fast 分支 [RuoYi-Vue-Plus-fast](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/tree/fast/)
* Oracle 模块 oracle 分支 [RuoYi-Vue-Plus-oracle](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/tree/oracle/)
-## 关注作者(扫码请备注: "加群")
-
-
+## 扫码加群 一起交流
+
## 捐献作者
作者为兼职做开源,平时还需要工作,如果帮到了您可以请作者吃个盒饭
diff --git a/docker/deploy.sh b/docker/deploy.sh
new file mode 100644
index 000000000..3b6e69654
--- /dev/null
+++ b/docker/deploy.sh
@@ -0,0 +1,92 @@
+#!/bin/bash
+
+#使用说明,用来提示输入参数
+usage() {
+ echo "Usage: sh 执行脚本.sh [port|mount|monitor|base|start|stop|stopall|rm|rmiNoneTag]"
+ exit 1
+}
+
+#开启所需端口
+port(){
+ firewall-cmd --add-port=3306/tcp --permanent
+ firewall-cmd --add-port=6379/tcp --permanent
+ service firewalld restart
+}
+
+##放置挂载文件
+mount(){
+ #挂载配置文件
+ if test ! -f "/docker/nginx/conf/nginx.conf" ;then
+ mkdir -p /docker/nginx/conf
+ cp nginx/nginx.conf /docker/nginx/conf/nginx.conf
+ fi
+}
+
+#启动基础模块
+base(){
+ docker-compose up -d mysql nginx-web redis
+}
+
+#启动基础模块
+monitor(){
+ docker-compose up -d ruoyi-monitor-admin
+}
+
+#启动程序模块
+start(){
+ docker-compose up -d ruoyi-server1 ruoyi-server2
+}
+
+#停止程序模块
+stop(){
+ docker-compose stop ruoyi-server1 ruoyi-server2
+}
+
+#关闭所有模块
+stopall(){
+ docker-compose stop
+}
+
+#删除所有模块
+rm(){
+ docker-compose rm
+}
+
+#删除Tag为空的镜像
+rmiNoneTag(){
+ docker images|grep none|awk '{print $3}'|xargs docker rmi -f
+}
+
+#根据输入参数,选择执行对应方法,不输入则执行使用说明
+case "$1" in
+"port")
+ port
+;;
+"mount")
+ mount
+;;
+"base")
+ base
+;;
+"monitor")
+ monitor
+;;
+"start")
+ start
+;;
+"stop")
+ stop
+;;
+"stopall")
+ stopall
+;;
+"rm")
+ rm
+;;
+"rmiNoneTag")
+ rmiNoneTag
+;;
+*)
+ usage
+;;
+esac
diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml
new file mode 100644
index 000000000..d40ae29e7
--- /dev/null
+++ b/docker/docker-compose.yml
@@ -0,0 +1,119 @@
+version: '3'
+
+services:
+ mysql:
+ image: mysql:8.0.24
+ container_name: mysql
+ environment:
+ # 时区上海
+ TZ: Asia/Shanghai
+ # root 密码
+ MYSQL_ROOT_PASSWORD: root
+ # 初始化数据库(后续的初始化sql会在这个库执行)
+ MYSQL_DATABASE: ry-vue
+ ports:
+ - 3306:3306
+ volumes:
+ # 数据挂载
+ - /docker/mysql/data/:/var/lib/mysql/
+ # 配置挂载
+ - /docker/mysql/conf/:/etc/mysql/conf.d/
+ command:
+ # 将mysql8.0默认密码策略 修改为 原先 策略 (mysql8.0对其默认策略做了更改 会导致密码无法匹配)
+ --default-authentication-plugin=mysql_native_password
+ --character-set-server=utf8mb4
+ --collation-server=utf8mb4_general_ci
+ --explicit_defaults_for_timestamp=true
+ --lower_case_table_names=1
+ privileged: true
+ restart: always
+ networks:
+ ruoyi_net:
+ ipv4_address: 172.30.0.36
+
+ nginx-web:
+ # 如果需要指定版本 就把 latest 换成版本号
+ image: nginx:latest
+ container_name: nginx-web
+ ports:
+ - 80:80
+ - 443:443
+ volumes:
+ # 证书映射
+ - /docker/nginx/cert:/etc/nginx/cert
+ # 配置文件映射
+ - /docker/nginx/conf/nginx.conf:/etc/nginx/nginx.conf
+ # 页面目录
+ - /docker/nginx/html:/usr/share/nginx/html
+ # 日志目录
+ - /docker/nginx/log:/var/log/nginx
+ # 主机本机时间文件映射 与本机时间同步
+ - /etc/localtime:/etc/localtime:ro
+ privileged: true
+ restart: always
+ networks:
+ - ruoyi_net
+
+ redis:
+ image: redis:6.2.1
+ container_name: redis
+ ports:
+ - 6379:6379
+ environment:
+ # 设置环境变量 时区上海 编码UTF-8
+ TZ: Asia/Shanghai
+ LANG: en_US.UTF-8
+ volumes:
+ # 配置文件
+ - /docker/redis/conf/redis.conf:/redis.conf:rw
+ # 数据文件
+ - /docker/redis/data:/data:rw
+ command: "redis-server --appendonly yes"
+ privileged: true
+ restart: always
+ networks:
+ ruoyi_net:
+ ipv4_address: 172.30.0.48
+
+ ruoyi-server1:
+ image: "ruoyi/ruoyi-server:2.5.0"
+ environment:
+ - TZ=Asia/Shanghai
+ volumes:
+ # 配置文件
+ - /docker/server1/logs/:/ruoyi/server/logs/
+ privileged: true
+ restart: always
+ networks:
+ ruoyi_net:
+ ipv4_address: 172.30.0.60
+
+ ruoyi-server2:
+ image: "ruoyi/ruoyi-server:2.5.0"
+ environment:
+ - TZ=Asia/Shanghai
+ volumes:
+ # 配置文件
+ - /docker/server2/logs/:/ruoyi/server/logs/
+ privileged: true
+ restart: always
+ networks:
+ ruoyi_net:
+ ipv4_address: 172.30.0.61
+
+ ruoyi-monitor-admin:
+ image: "ruoyi/ruoyi-monitor-admin:2.5.0"
+ environment:
+ - TZ=Asia/Shanghai
+ privileged: true
+ restart: always
+ networks:
+ ruoyi_net:
+ ipv4_address: 172.30.0.90
+
+networks:
+ ruoyi_net:
+ driver: bridge
+ ipam:
+ config:
+ - subnet: 172.30.0.0/16
diff --git a/docker/nginx/nginx.conf b/docker/nginx/nginx.conf
new file mode 100644
index 000000000..66ac29e3e
--- /dev/null
+++ b/docker/nginx/nginx.conf
@@ -0,0 +1,77 @@
+worker_processes 1;
+
+error_log /var/log/nginx/error.log warn;
+pid /var/run/nginx.pid;
+
+events {
+ worker_connections 1024;
+}
+
+http {
+ include mime.types;
+ default_type application/octet-stream;
+ sendfile on;
+ keepalive_timeout 65;
+ # 限制body大小
+ client_max_body_size 100m;
+
+ log_format main '$remote_addr - $remote_user [$time_local] "$request" '
+ '$status $body_bytes_sent "$http_referer" '
+ '"$http_user_agent" "$http_x_forwarded_for"';
+
+ access_log /var/log/nginx/access.log main;
+
+ upstream server {
+ server 172.30.0.60:8080;
+ server 172.30.0.61:8080;
+ }
+
+ upstream monitor-admin {
+ server 172.30.0.90:9090;
+ }
+
+ server {
+ listen 80;
+ server_name localhost;
+
+ # https配置参考 start
+ #listen 443 ssl;
+
+ # 证书直接存放 /docker/nginx/cert/ 目录下即可 更改证书名称即可 无需更改证书路径
+ #ssl on;
+ #ssl_certificate /etc/nginx/cert/xxx.local.crt; # /etc/nginx/cert/ 为docker映射路径 不允许更改
+ #ssl_certificate_key /etc/nginx/cert/xxx.local.key; # /etc/nginx/cert/ 为docker映射路径 不允许更改
+ #ssl_session_timeout 5m;
+ #ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
+ #ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
+ #ssl_prefer_server_ciphers on;
+ # https配置参考 end
+
+ location / {
+ root /usr/share/nginx/html;
+ try_files $uri $uri/ /index.html;
+ index index.html index.htm;
+ }
+
+ location /prod-api/ {
+ proxy_set_header Host $http_host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header REMOTE-HOST $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_pass http://server/;
+ }
+
+ location /admin/ {
+ proxy_set_header Host $http_host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header REMOTE-HOST $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_pass http://monitor-admin/admin/;
+ }
+
+ error_page 500 502 503 504 /50x.html;
+ location = /50x.html {
+ root html;
+ }
+ }
+}
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 000000000..2029dc442
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,280 @@
+
+
+ 4.0.0
+
+ com.ruoyi
+ ruoyi-vue-plus
+ 2.5.0
+
+ RuoYi-Vue-Plus
+ https://gitee.com/JavaLionLi/RuoYi-Vue-Plus
+ RuoYi-Vue-Plus后台管理系统
+
+
+ 2.5.0
+ 2.4.8
+ UTF-8
+ UTF-8
+ 1.8
+ 3.1.1
+ 1.2.6
+ 3.0.3
+ 4.1.2
+ 1.7
+ 0.9.1
+ 3.4.3
+ 5.7.4
+ 3.0.3
+ 11.0
+ 2.4.3
+ 3.16.0
+ 2.2.1
+ 3.4.0
+
+
+ localhost
+ http://${docker.registry.url}:2375
+ ruoyi
+ 1.2.0
+
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-dependencies
+ ${spring-boot.version}
+ pom
+ import
+
+
+
+
+ com.alibaba
+ druid-spring-boot-starter
+ ${druid.version}
+
+
+
+ com.github.xiaoymin
+ knife4j-spring-boot-starter
+ ${knife4j.version}
+
+
+
+
+ org.apache.poi
+ poi-ooxml
+ ${poi.version}
+
+
+
+
+ org.apache.velocity
+ velocity
+ ${velocity.version}
+
+
+
+
+ io.jsonwebtoken
+ jjwt
+ ${jwt.version}
+
+
+
+
+ com.baomidou
+ dynamic-datasource-spring-boot-starter
+ ${datasource.version}
+
+
+
+ com.baomidou
+ mybatis-plus-boot-starter
+ ${mybatis-plus.version}
+
+
+ com.baomidou
+ mybatis-plus-extension
+ ${mybatis-plus.version}
+
+
+
+ cn.hutool
+ hutool-all
+ ${hutool.version}
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-openfeign
+ ${feign.version}
+
+
+
+ io.github.openfeign
+ feign-okhttp
+ ${feign-okhttp.version}
+
+
+
+ de.codecentric
+ spring-boot-admin-starter-server
+ ${spring-boot-admin.version}
+
+
+ de.codecentric
+ spring-boot-admin-starter-client
+ ${spring-boot-admin.version}
+
+
+
+
+ org.redisson
+ redisson-spring-boot-starter
+ ${redisson.version}
+
+
+ com.baomidou
+ lock4j-redisson-spring-boot-starter
+ ${lock4j.version}
+
+
+
+
+
+
+ ruoyi
+ ruoyi-extend
+
+ pom
+
+
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.1
+
+ ${java.version}
+ ${java.version}
+ ${project.build.sourceEncoding}
+
+
+
+
+
+
+ src/main/resources
+
+ true
+
+
+
+
+
+
+ public
+ aliyun nexus
+ http://maven.aliyun.com/nexus/content/groups/public/
+
+ true
+
+
+
+
+
+
+ public
+ aliyun nexus
+ http://maven.aliyun.com/nexus/content/groups/public/
+
+ true
+
+
+ false
+
+
+
+
+
+
+ local
+
+
+ local
+ debug
+
+
+
+ dev
+
+
+ dev
+ debug
+
+
+
+ true
+
+
+
+ prod
+
+ prod
+ warn
+
+
+
+
+
+ jdk8
+
+ true
+ 1.8
+
+
+ 1.8
+
+
+
+ jdk11
+
+ 11
+
+
+ 11
+ 3.0.1
+
+
+
+
+
+ com.sun.xml.bind
+ jaxb-impl
+ ${jaxb.version}
+
+
+
+
+
+
+ com.sun.xml.bind
+ jaxb-impl
+
+
+
+
+
+
diff --git a/ruoyi-extend/pom.xml b/ruoyi-extend/pom.xml
new file mode 100644
index 000000000..e71a426cc
--- /dev/null
+++ b/ruoyi-extend/pom.xml
@@ -0,0 +1,18 @@
+
+
+
+ ruoyi-vue-plus
+ com.ruoyi
+ 2.5.0
+
+ 4.0.0
+ ruoyi-extend
+ pom
+
+
+ ruoyi-monitor-admin
+
+
+
diff --git a/ruoyi-extend/ruoyi-monitor-admin/Dockerfile b/ruoyi-extend/ruoyi-monitor-admin/Dockerfile
new file mode 100644
index 000000000..ef551fec3
--- /dev/null
+++ b/ruoyi-extend/ruoyi-monitor-admin/Dockerfile
@@ -0,0 +1,13 @@
+FROM anapsix/alpine-java:8_server-jre_unlimited
+
+MAINTAINER Lion Li
+
+RUN mkdir -p /ruoyi/monitor
+
+WORKDIR /ruoyi/monitor
+
+EXPOSE 9090
+
+ADD ./target/ruoyi-monitor-admin.jar ./app.jar
+
+ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "app.jar"]
diff --git a/ruoyi-extend/ruoyi-monitor-admin/pom.xml b/ruoyi-extend/ruoyi-monitor-admin/pom.xml
new file mode 100644
index 000000000..e9d48d665
--- /dev/null
+++ b/ruoyi-extend/ruoyi-monitor-admin/pom.xml
@@ -0,0 +1,73 @@
+
+
+
+ ruoyi-extend
+ com.ruoyi
+ 2.5.0
+
+ 4.0.0
+ jar
+ ruoyi-monitor-admin
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-security
+
+
+
+ de.codecentric
+ spring-boot-admin-starter-server
+
+
+
+
+ ${project.artifactId}
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+ ${spring-boot.version}
+
+ true
+
+
+
+
+ repackage
+
+
+
+
+
+ com.spotify
+ docker-maven-plugin
+ ${docker.plugin.version}
+
+ ${docker.namespace}/${project.artifactId}:${project.version}
+ ${project.basedir}
+ ${docker.registry.host}
+ ${docker.registry.url}
+ ${docker.registry.url}
+
+
+ /
+ ${project.build.directory}
+ ${project.build.finalName}.jar
+
+
+
+
+
+
+
+
diff --git a/ruoyi-extend/ruoyi-monitor-admin/src/main/java/com/ruoyi/monitor/admin/MonitorAdminApplication.java b/ruoyi-extend/ruoyi-monitor-admin/src/main/java/com/ruoyi/monitor/admin/MonitorAdminApplication.java
new file mode 100644
index 000000000..1d1cbca58
--- /dev/null
+++ b/ruoyi-extend/ruoyi-monitor-admin/src/main/java/com/ruoyi/monitor/admin/MonitorAdminApplication.java
@@ -0,0 +1,19 @@
+package com.ruoyi.monitor.admin;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+/**
+ * Admin 监控启动程序
+ *
+ * @author Lion Li
+ */
+@SpringBootApplication
+public class MonitorAdminApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(MonitorAdminApplication.class, args);
+ System.out.println("Admin 监控启动成功" );
+ }
+
+}
diff --git a/ruoyi-extend/ruoyi-monitor-admin/src/main/java/com/ruoyi/monitor/admin/config/AdminServerConfig.java b/ruoyi-extend/ruoyi-monitor-admin/src/main/java/com/ruoyi/monitor/admin/config/AdminServerConfig.java
new file mode 100644
index 000000000..e2a9c51de
--- /dev/null
+++ b/ruoyi-extend/ruoyi-monitor-admin/src/main/java/com/ruoyi/monitor/admin/config/AdminServerConfig.java
@@ -0,0 +1,31 @@
+package com.ruoyi.monitor.admin.config;
+
+import de.codecentric.boot.admin.server.config.EnableAdminServer;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration;
+import org.springframework.boot.task.TaskExecutorBuilder;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+
+import java.util.concurrent.Executor;
+
+/**
+ * springboot-admin server配置类
+ *
+ * @author Lion Li
+ */
+@Configuration
+@EnableAdminServer
+public class AdminServerConfig {
+
+ @Lazy
+ @Bean(name = TaskExecutionAutoConfiguration.APPLICATION_TASK_EXECUTOR_BEAN_NAME)
+ @ConditionalOnMissingBean(Executor.class)
+ public ThreadPoolTaskExecutor applicationTaskExecutor(TaskExecutorBuilder builder) {
+ return builder.build();
+ }
+
+
+}
diff --git a/ruoyi-extend/ruoyi-monitor-admin/src/main/java/com/ruoyi/monitor/admin/config/SecurityConfig.java b/ruoyi-extend/ruoyi-monitor-admin/src/main/java/com/ruoyi/monitor/admin/config/SecurityConfig.java
new file mode 100644
index 000000000..98834a9bc
--- /dev/null
+++ b/ruoyi-extend/ruoyi-monitor-admin/src/main/java/com/ruoyi/monitor/admin/config/SecurityConfig.java
@@ -0,0 +1,48 @@
+package com.ruoyi.monitor.admin.config;
+
+import de.codecentric.boot.admin.server.config.AdminServerProperties;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
+
+/**
+ * spring security配置
+ *
+ * @author ruoyi
+ */
+@Configuration
+@EnableWebSecurity
+@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, proxyTargetClass = true)
+public class SecurityConfig extends WebSecurityConfigurerAdapter {
+
+ private final String adminContextPath;
+
+ public SecurityConfig(AdminServerProperties adminServerProperties) {
+ this.adminContextPath = adminServerProperties.getContextPath();
+ }
+
+ @Override
+ protected void configure(HttpSecurity httpSecurity) throws Exception {
+ SavedRequestAwareAuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler();
+ successHandler.setTargetUrlParameter("redirectTo");
+ successHandler.setDefaultTargetUrl(adminContextPath + "/");
+
+ httpSecurity.authorizeRequests()
+ //授予对所有静态资产和登录页面的公共访问权限。
+ .antMatchers(adminContextPath + "/assets/**").permitAll()
+ .antMatchers(adminContextPath + "/login").permitAll()
+ //必须对每个其他请求进行身份验证
+ .anyRequest().authenticated().and()
+ //配置登录和注销
+ .formLogin().loginPage(adminContextPath + "/login")
+ .successHandler(successHandler).and()
+ .logout().logoutUrl(adminContextPath + "/logout").and()
+ //启用HTTP-Basic支持。这是Spring Boot Admin Client注册所必需的
+ .httpBasic().and().csrf().disable()
+ .headers().frameOptions().disable();
+ }
+
+}
diff --git a/ruoyi-extend/ruoyi-monitor-admin/src/main/resources/application.yml b/ruoyi-extend/ruoyi-monitor-admin/src/main/resources/application.yml
new file mode 100644
index 000000000..631f3e772
--- /dev/null
+++ b/ruoyi-extend/ruoyi-monitor-admin/src/main/resources/application.yml
@@ -0,0 +1,11 @@
+server:
+ port: 9090
+
+spring:
+ security:
+ user:
+ name: ruoyi
+ password: 123456
+ boot:
+ admin:
+ context-path: /admin
diff --git a/ruoyi-ui/.env.development b/ruoyi-ui/.env.development
index abb97d464..a1a508de4 100644
--- a/ruoyi-ui/.env.development
+++ b/ruoyi-ui/.env.development
@@ -7,5 +7,8 @@ ENV = 'development'
# 若依管理系统/开发环境
VUE_APP_BASE_API = '/dev-api'
+# 监控地址
+VUE_APP_MONITRO_ADMIN = 'http://localhost:9090/admin/login'
+
# 路由懒加载
VUE_CLI_BABEL_TRANSPILE_MODULES = true
diff --git a/ruoyi-ui/.env.production b/ruoyi-ui/.env.production
index 7179b3291..b6eec53c6 100644
--- a/ruoyi-ui/.env.production
+++ b/ruoyi-ui/.env.production
@@ -4,5 +4,8 @@ VUE_APP_TITLE = RuoYi-Vue-Plus后台管理系统
# 生产环境配置
ENV = 'production'
+# 监控地址
+VUE_APP_MONITRO_ADMIN = '/admin/login'
+
# 若依管理系统/生产环境
VUE_APP_BASE_API = '/prod-api'
diff --git a/ruoyi-ui/.env.staging b/ruoyi-ui/.env.staging
index b5723d7b8..e74ce6ce2 100644
--- a/ruoyi-ui/.env.staging
+++ b/ruoyi-ui/.env.staging
@@ -6,5 +6,8 @@ NODE_ENV = production
# 测试环境配置
ENV = 'staging'
+# 监控地址
+VUE_APP_MONITRO_ADMIN = '/admin/login'
+
# 若依管理系统/测试环境
VUE_APP_BASE_API = '/stage-api'
diff --git a/ruoyi-ui/package.json b/ruoyi-ui/package.json
index af8db7e87..648b17292 100644
--- a/ruoyi-ui/package.json
+++ b/ruoyi-ui/package.json
@@ -1,6 +1,6 @@
{
"name": "ruoyi-vue-plus",
- "version": "2.4.0",
+ "version": "2.5.0",
"description": "RuoYi-Vue-Plus后台管理系统",
"author": "LionLi",
"license": "MIT",
diff --git a/ruoyi-ui/src/api/system/role.js b/ruoyi-ui/src/api/system/role.js
index 463501ce8..c669ac43a 100644
--- a/ruoyi-ui/src/api/system/role.js
+++ b/ruoyi-ui/src/api/system/role.js
@@ -72,4 +72,50 @@ export function exportRole(query) {
method: 'get',
params: query
})
-}
\ No newline at end of file
+}
+
+
+// 查询角色已授权用户列表
+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
+ })
+}
diff --git a/ruoyi-ui/src/api/system/user.js b/ruoyi-ui/src/api/system/user.js
index 3b9a776a7..37f4eb338 100644
--- a/ruoyi-ui/src/api/system/user.js
+++ b/ruoyi-ui/src/api/system/user.js
@@ -125,3 +125,20 @@ export function importTemplate() {
method: 'get'
})
}
+
+// 查询授权角色
+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
+ })
+}
diff --git a/ruoyi-ui/src/assets/styles/ruoyi.scss b/ruoyi-ui/src/assets/styles/ruoyi.scss
index dee6d091c..c4b43658f 100644
--- a/ruoyi-ui/src/assets/styles/ruoyi.scss
+++ b/ruoyi-ui/src/assets/styles/ruoyi.scss
@@ -53,6 +53,13 @@
margin-left: 20px;
}
+.h1, .h2, .h3, .h4, .h5, .h6, h1, h2, h3, h4, h5, h6 {
+ font-family: inherit;
+ font-weight: 500;
+ line-height: 1.1;
+ color: inherit;
+}
+
.el-dialog:not(.is-fullscreen){
margin-top: 6vh !important;
}
@@ -120,6 +127,17 @@
width: inherit;
}
+/** 表格更多操作下拉样式 */
+.el-table .el-dropdown-link {
+ cursor: pointer;
+ color: #1890ff;
+ margin-left: 5px;
+}
+
+.el-table .el-dropdown, .el-icon-arrow-down {
+ font-size: 12px;
+}
+
.el-tree-node__content > .el-checkbox {
margin-right: 8px;
}
diff --git a/ruoyi-ui/src/components/Editor/index.vue b/ruoyi-ui/src/components/Editor/index.vue
index d63a48d12..98b9fa79b 100644
--- a/ruoyi-ui/src/components/Editor/index.vue
+++ b/ruoyi-ui/src/components/Editor/index.vue
@@ -9,7 +9,7 @@
:headers="headers"
style="display: none"
ref="upload"
- v-if="this.uploadUrl"
+ v-if="this.type == 'url'"
>
@@ -46,14 +46,15 @@ export default {
type: Boolean,
default: false,
},
- /* 上传地址 */
- uploadUrl: {
+ /* 类型(base64格式、url格式) */
+ type: {
type: String,
- default: "",
+ default: "url",
}
},
data() {
return {
+ uploadUrl: process.env.VUE_APP_BASE_API + "/common/upload", // 上传的图片服务器地址
headers: {
Authorization: "Bearer " + getToken()
},
@@ -119,7 +120,7 @@ export default {
const editor = this.$refs.editor;
this.Quill = new Quill(editor, this.options);
// 如果设置了上传地址则自定义图片上传事件
- if (this.uploadUrl) {
+ if (this.type == 'url') {
let toolbar = this.Quill.getModule("toolbar");
toolbar.addHandler("image", (value) => {
this.uploadType = "image";
@@ -165,7 +166,7 @@ export default {
// 获取光标所在位置
let length = quill.getSelection().index;
// 插入图片 res.url为服务器返回的图片地址
- quill.insertEmbed(length, "image", res.url);
+ quill.insertEmbed(length, "image", process.env.VUE_APP_BASE_API + res.data.fileName);
// 调整光标到最后
quill.setSelection(length + 1);
} else {
diff --git a/ruoyi-ui/src/components/FileUpload/index.vue b/ruoyi-ui/src/components/FileUpload/index.vue
index 3c3d17bf0..d47fb98f3 100644
--- a/ruoyi-ui/src/components/FileUpload/index.vue
+++ b/ruoyi-ui/src/components/FileUpload/index.vue
@@ -1,179 +1,198 @@
-
-
-
-
- 选取文件
-
-
- 请上传
- 大小不超过 {{ fileSize }}MB
- 格式为 {{ fileType.join("/") }}
- 的文件
-
-
-
-
-
-
-
- {{ getFileName(file.name) }}
-
-
- 删除
-
-
-
-
-
-
-
-
-
+
+
+
+
+ 选取文件
+
+
+ 请上传
+ 大小不超过 {{ fileSize }}MB
+ 格式为 {{ fileType.join("/") }}
+ 的文件
+
+
+
+
+
+
+
+ {{ getFileName(file.name) }}
+
+
+ 删除
+
+
+
+
+
+
+
+
+
diff --git a/ruoyi-ui/src/components/HeaderSearch/index.vue b/ruoyi-ui/src/components/HeaderSearch/index.vue
index ce9f305f9..c44eff56e 100644
--- a/ruoyi-ui/src/components/HeaderSearch/index.vue
+++ b/ruoyi-ui/src/components/HeaderSearch/index.vue
@@ -70,9 +70,11 @@ export default {
this.show = false
},
change(val) {
+ const path = val.path;
if(this.ishttp(val.path)) {
// http(s):// 路径新窗口打开
- window.open(val.path, "_blank");
+ const pindex = path.indexOf("http");
+ window.open(path.substr(pindex, path.length), "_blank");
} else {
this.$router.push(val.path)
}
diff --git a/ruoyi-ui/src/components/ImageUpload/index.vue b/ruoyi-ui/src/components/ImageUpload/index.vue
index 995b27794..f2a7402b3 100644
--- a/ruoyi-ui/src/components/ImageUpload/index.vue
+++ b/ruoyi-ui/src/components/ImageUpload/index.vue
@@ -1,100 +1,210 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+ 请上传
+ 大小不超过 {{ fileSize }}MB
+ 格式为 {{ fileType.join("/") }}
+ 的文件
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ruoyi-ui/src/components/TopNav/index.vue b/ruoyi-ui/src/components/TopNav/index.vue
index d89930a88..c8837f2a0 100644
--- a/ruoyi-ui/src/components/TopNav/index.vue
+++ b/ruoyi-ui/src/components/TopNav/index.vue
@@ -73,9 +73,9 @@ export default {
if(router.path === "/") {
router.children[item].path = "/redirect/" + router.children[item].path;
} else {
- if(!this.ishttp(router.children[item].path)) {
+ if(!this.ishttp(router.children[item].path)) {
router.children[item].path = router.path + "/" + router.children[item].path;
- }
+ }
}
router.children[item].parentPath = router.path;
}
diff --git a/ruoyi-ui/src/directive/dialog/drag.js b/ruoyi-ui/src/directive/dialog/drag.js
new file mode 100644
index 000000000..2e823465e
--- /dev/null
+++ b/ruoyi-ui/src/directive/dialog/drag.js
@@ -0,0 +1,64 @@
+/**
+* v-dialogDrag 弹窗拖拽
+* Copyright (c) 2019 ruoyi
+*/
+
+export default {
+ bind(el, binding, vnode, oldVnode) {
+ const value = binding.value
+ if (value == false) return
+ // 获取拖拽内容头部
+ const dialogHeaderEl = el.querySelector('.el-dialog__header');
+ const dragDom = el.querySelector('.el-dialog');
+ dialogHeaderEl.style.cursor = 'move';
+ // 获取原有属性 ie dom元素.currentStyle 火狐谷歌 window.getComputedStyle(dom元素, null);
+ const sty = dragDom.currentStyle || window.getComputedStyle(dragDom, null);
+ dragDom.style.position = 'absolute';
+ dragDom.style.marginTop = 0;
+ let width = dragDom.style.width;
+ if (width.includes('%')) {
+ width = +document.body.clientWidth * (+width.replace(/\%/g, '') / 100);
+ } else {
+ width = +width.replace(/\px/g, '');
+ }
+ dragDom.style.left = `${(document.body.clientWidth - width) / 2}px`;
+ // 鼠标按下事件
+ dialogHeaderEl.onmousedown = (e) => {
+ // 鼠标按下,计算当前元素距离可视区的距离 (鼠标点击位置距离可视窗口的距离)
+ const disX = e.clientX - dialogHeaderEl.offsetLeft;
+ const disY = e.clientY - dialogHeaderEl.offsetTop;
+
+ // 获取到的值带px 正则匹配替换
+ let styL, styT;
+
+ // 注意在ie中 第一次获取到的值为组件自带50% 移动之后赋值为px
+ if (sty.left.includes('%')) {
+ styL = +document.body.clientWidth * (+sty.left.replace(/\%/g, '') / 100);
+ styT = +document.body.clientHeight * (+sty.top.replace(/\%/g, '') / 100);
+ } else {
+ styL = +sty.left.replace(/\px/g, '');
+ styT = +sty.top.replace(/\px/g, '');
+ };
+
+ // 鼠标拖拽事件
+ document.onmousemove = function (e) {
+ // 通过事件委托,计算移动的距离 (开始拖拽至结束拖拽的距离)
+ const l = e.clientX - disX;
+ const t = e.clientY - disY;
+
+ let finallyL = l + styL
+ let finallyT = t + styT
+
+ // 移动当前元素
+ dragDom.style.left = `${finallyL}px`;
+ dragDom.style.top = `${finallyT}px`;
+
+ };
+
+ document.onmouseup = function (e) {
+ document.onmousemove = null;
+ document.onmouseup = null;
+ };
+ }
+ }
+};
\ No newline at end of file
diff --git a/ruoyi-ui/src/directive/index.js b/ruoyi-ui/src/directive/index.js
new file mode 100644
index 000000000..550109b4d
--- /dev/null
+++ b/ruoyi-ui/src/directive/index.js
@@ -0,0 +1,18 @@
+import hasRole from './permission/hasRole'
+import hasPermi from './permission/hasPermi'
+import dialogDrag from './dialog/drag'
+
+const install = function(Vue) {
+ Vue.directive('hasRole', hasRole)
+ Vue.directive('hasPermi', hasPermi)
+ Vue.directive('dialogDrag', dialogDrag)
+}
+
+if (window.Vue) {
+ window['hasRole'] = hasRole
+ window['hasPermi'] = hasPermi
+ window['dialogDrag'] = dialogDrag
+ Vue.use(install); // eslint-disable-line
+}
+
+export default install
diff --git a/ruoyi-ui/src/directive/permission/hasPermi.js b/ruoyi-ui/src/directive/permission/hasPermi.js
index d7107cec0..7101e3e83 100644
--- a/ruoyi-ui/src/directive/permission/hasPermi.js
+++ b/ruoyi-ui/src/directive/permission/hasPermi.js
@@ -1,8 +1,8 @@
/**
- * 操作权限处理
+ * v-hasPermi 操作权限处理
* Copyright (c) 2019 ruoyi
*/
-
+
import store from '@/store'
export default {
diff --git a/ruoyi-ui/src/directive/permission/hasRole.js b/ruoyi-ui/src/directive/permission/hasRole.js
index 13038099d..ad9d4d79d 100644
--- a/ruoyi-ui/src/directive/permission/hasRole.js
+++ b/ruoyi-ui/src/directive/permission/hasRole.js
@@ -1,8 +1,8 @@
/**
- * 角色权限处理
+ * v-hasRole 角色权限处理
* Copyright (c) 2019 ruoyi
*/
-
+
import store from '@/store'
export default {
diff --git a/ruoyi-ui/src/layout/components/AppMain.vue b/ruoyi-ui/src/layout/components/AppMain.vue
index a89763806..0c6f4b784 100644
--- a/ruoyi-ui/src/layout/components/AppMain.vue
+++ b/ruoyi-ui/src/layout/components/AppMain.vue
@@ -51,7 +51,7 @@ export default {
// fix css style bug in open el-dialog
.el-popup-parent--hidden {
.fixed-header {
- padding-right: 15px;
+ padding-right: 17px;
}
}
diff --git a/ruoyi-ui/src/layout/components/InnerLink/index.vue b/ruoyi-ui/src/layout/components/InnerLink/index.vue
new file mode 100644
index 000000000..a45d1a4a4
--- /dev/null
+++ b/ruoyi-ui/src/layout/components/InnerLink/index.vue
@@ -0,0 +1,27 @@
+
diff --git a/ruoyi-ui/src/main.js b/ruoyi-ui/src/main.js
index d1f8973b7..d07dead41 100644
--- a/ruoyi-ui/src/main.js
+++ b/ruoyi-ui/src/main.js
@@ -10,7 +10,7 @@ import '@/assets/styles/ruoyi.scss' // ruoyi css
import App from './App'
import store from './store'
import router from './router'
-import permission from './directive/permission'
+import directive from './directive' //directive
import './assets/icons' // icon
import './permission' // permission control
@@ -20,6 +20,12 @@ import { parseTime, resetForm, addDateRange, selectDictLabel, selectDictLabels,
import Pagination from "@/components/Pagination";
// 自定义表格工具组件
import RightToolbar from "@/components/RightToolbar"
+// 富文本组件
+import Editor from "@/components/Editor"
+// 文件上传组件
+import FileUpload from "@/components/FileUpload"
+// 图片上传组件
+import ImageUpload from "@/components/ImageUpload"
// 字典标签组件
import DictTag from '@/components/DictTag'
// 头部标签组件
@@ -52,8 +58,11 @@ Vue.prototype.msgInfo = function (msg) {
Vue.component('DictTag', DictTag)
Vue.component('Pagination', Pagination)
Vue.component('RightToolbar', RightToolbar)
+Vue.component('Editor', Editor)
+Vue.component('FileUpload', FileUpload)
+Vue.component('ImageUpload', ImageUpload)
-Vue.use(permission)
+Vue.use(directive)
Vue.use(VueMeta)
/**
diff --git a/ruoyi-ui/src/router/index.js b/ruoyi-ui/src/router/index.js
index ffb12e7d5..c7b9371b5 100644
--- a/ruoyi-ui/src/router/index.js
+++ b/ruoyi-ui/src/router/index.js
@@ -6,6 +6,7 @@ Vue.use(Router)
/* Layout */
import Layout from '@/layout'
import ParentView from '@/components/ParentView';
+import InnerLink from '@/layout/components/InnerLink'
/**
* Note: 路由配置项
@@ -80,6 +81,32 @@ export const constantRoutes = [
}
]
},
+ {
+ path: '/auth',
+ component: Layout,
+ hidden: true,
+ children: [
+ {
+ path: 'role/:userId(\\d+)',
+ component: (resolve) => require(['@/views/system/user/authRole'], resolve),
+ name: 'AuthRole',
+ meta: { title: '分配角色'}
+ }
+ ]
+ },
+ {
+ path: '/auth',
+ component: Layout,
+ hidden: true,
+ children: [
+ {
+ path: 'user/:roleId(\\d+)',
+ component: (resolve) => require(['@/views/system/role/authUser'], resolve),
+ name: 'AuthUser',
+ meta: { title: '分配用户'}
+ }
+ ]
+ },
{
path: '/dict',
component: Layout,
diff --git a/ruoyi-ui/src/store/modules/permission.js b/ruoyi-ui/src/store/modules/permission.js
index aacfc8c93..81026f367 100644
--- a/ruoyi-ui/src/store/modules/permission.js
+++ b/ruoyi-ui/src/store/modules/permission.js
@@ -2,6 +2,7 @@ import { constantRoutes } from '@/router'
import { getRouters } from '@/api/menu'
import Layout from '@/layout/index'
import ParentView from '@/components/ParentView';
+import InnerLink from '@/layout/components/InnerLink'
const permission = {
state: {
@@ -65,6 +66,8 @@ function filterAsyncRouter(asyncRouterMap, lastRouter = false, type = false) {
route.component = Layout
} else if (route.component === 'ParentView') {
route.component = ParentView
+ } else if (route.component === 'InnerLink') {
+ route.component = InnerLink
} else {
route.component = loadView(route.component)
}
diff --git a/ruoyi-ui/src/views/demo/demo/index.vue b/ruoyi-ui/src/views/demo/demo/index.vue
index 279c4693c..a6679f390 100644
--- a/ruoyi-ui/src/views/demo/demo/index.vue
+++ b/ruoyi-ui/src/views/demo/demo/index.vue
@@ -304,17 +304,19 @@ export default {
this.buttonLoading = true;
if (this.form.id != null) {
updateDemo(this.form).then(response => {
- this.buttonLoading = false;
this.msgSuccess("修改成功");
this.open = false;
this.getList();
+ }).finally(() => {
+ this.buttonLoading = false;
});
} else {
addDemo(this.form).then(response => {
- this.buttonLoading = false;
this.msgSuccess("新增成功");
this.open = false;
this.getList();
+ }).finally(() => {
+ this.buttonLoading = false;
});
}
}
diff --git a/ruoyi-ui/src/views/demo/tree/index.vue b/ruoyi-ui/src/views/demo/tree/index.vue
index afe96c4ae..57b152fc9 100644
--- a/ruoyi-ui/src/views/demo/tree/index.vue
+++ b/ruoyi-ui/src/views/demo/tree/index.vue
@@ -255,17 +255,19 @@ export default {
this.buttonLoading = true;
if (this.form.id != null) {
updateTree(this.form).then(response => {
- this.buttonLoading = false;
this.msgSuccess("修改成功");
this.open = false;
this.getList();
+ }).finally(() => {
+ this.buttonLoading = false;
});
} else {
addTree(this.form).then(response => {
- this.buttonLoading = false;
this.msgSuccess("新增成功");
this.open = false;
this.getList();
+ }).finally(() => {
+ this.buttonLoading = false;
});
}
}
diff --git a/ruoyi-ui/src/views/index.vue b/ruoyi-ui/src/views/index.vue
index dba6dfe8b..671dcde2b 100644
--- a/ruoyi-ui/src/views/index.vue
+++ b/ruoyi-ui/src/views/index.vue
@@ -91,6 +91,32 @@
更新日志
+
+
+ - update springboot 2.4.7 => 2.4.8
+ - update knife4j 3.0.2 => 3.0.3
+ - update hutool 5.7.2 => 5.7.4
+ - update spring-boot-admin 2.4.1 => 2.4.3
+ - update redisson 3.15.2 => 3.16.0
+ - add 增加 docker 编排 与 shell 脚本
+ - add 增加 feign 熔断 自定义结构体解析方法 与 demo 注释
+ - add 用户管理新增分配角色功能
+ - add 角色管理新增分配用户功能
+ - add 增加spring-cache演示案例
+ - update 独立 springboot-admin 监控到扩展模块项目
+ - update springboot-admin 监控 增加用户登录权限管理
+ - update 优化代码生成器 批量导入
+ - update 优化 增加MP注入异常拦截
+ - update 关闭默认二级缓存 推荐使用 spring-cache 注解手动缓存
+ - update FileUpload ImageUpload组件 支持多图片上传
+ - update 优化中英文语言配置
+ - update 规范maven写法
+ - fix redis获取map属性bug修复。
+ - fix 修复 按钮loading 后端500卡死问题
+ - fix 相对路径下载问题
+ - fix 修复 hutool 工具返回结果不一致问题
+
+
- update springboot 2.3.11 => 2.4.7
diff --git a/ruoyi-ui/src/views/monitor/admin/index.vue b/ruoyi-ui/src/views/monitor/admin/index.vue
index f1d48b0ac..ad35dc463 100644
--- a/ruoyi-ui/src/views/monitor/admin/index.vue
+++ b/ruoyi-ui/src/views/monitor/admin/index.vue
@@ -1,26 +1,16 @@
-
-
-
+
diff --git a/ruoyi-ui/src/views/system/notice/index.vue b/ruoyi-ui/src/views/system/notice/index.vue
index 311554376..0ffd9d6c9 100644
--- a/ruoyi-ui/src/views/system/notice/index.vue
+++ b/ruoyi-ui/src/views/system/notice/index.vue
@@ -177,13 +177,9 @@
\ No newline at end of file
diff --git a/ruoyi-ui/src/views/system/role/index.vue b/ruoyi-ui/src/views/system/role/index.vue
index 081ea81d8..5bedd490d 100644
--- a/ruoyi-ui/src/views/system/role/index.vue
+++ b/ruoyi-ui/src/views/system/role/index.vue
@@ -124,7 +124,7 @@
-
+
修改
- 数据权限
删除
+ handleCommand(command, scope.row)">
+
+ 更多
+
+
+ 数据权限
+ 分配用户
+
+
@@ -469,6 +473,19 @@ export default {
this.single = selection.length!=1
this.multiple = !selection.length
},
+ // 更多操作触发
+ handleCommand(command, row) {
+ switch (command) {
+ case "handleDataScope":
+ this.handleDataScope(row);
+ break;
+ case "handleAuthUser":
+ this.handleAuthUser(row);
+ break;
+ default:
+ break;
+ }
+ },
// 树权限(展开/折叠)
handleCheckedTreeExpand(value, type) {
if (type == 'menu') {
@@ -548,6 +565,11 @@ export default {
this.title = "分配数据权限";
});
},
+ /** 分配用户操作 */
+ handleAuthUser: function(row) {
+ const roleId = row.roleId;
+ this.$router.push("/auth/user/" + roleId);
+ },
/** 提交按钮 */
submitForm: function() {
this.$refs["form"].validate(valid => {
diff --git a/ruoyi-ui/src/views/system/role/selectUser.vue b/ruoyi-ui/src/views/system/role/selectUser.vue
new file mode 100644
index 000000000..780b47f62
--- /dev/null
+++ b/ruoyi-ui/src/views/system/role/selectUser.vue
@@ -0,0 +1,142 @@
+
+
+
+
+
+
+
+
+
+
+
+ 搜索
+ 重置
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ parseTime(scope.row.createTime) }}
+
+
+
+
+
+
+
+
+
+
diff --git a/ruoyi-ui/src/views/system/user/authRole.vue b/ruoyi-ui/src/views/system/user/authRole.vue
new file mode 100644
index 000000000..8e7f82a99
--- /dev/null
+++ b/ruoyi-ui/src/views/system/user/authRole.vue
@@ -0,0 +1,117 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{(pageNum - 1) * pageSize + scope.$index + 1}}
+
+
+
+
+
+
+
+
+ {{ parseTime(scope.row.createTime) }}
+
+
+
+
+
+
+
+
+ 提交
+ 返回
+
+
+
+
+
+
diff --git a/ruoyi-ui/src/views/system/user/index.vue b/ruoyi-ui/src/views/system/user/index.vue
index 471e66f25..605cf6eeb 100644
--- a/ruoyi-ui/src/views/system/user/index.vue
+++ b/ruoyi-ui/src/views/system/user/index.vue
@@ -167,7 +167,7 @@
width="160"
class-name="small-padding fixed-width"
>
-
+
修改
删除
- 重置
+ handleCommand(command, scope.row)">
+
+ 更多
+
+
+ 重置密码
+ 分配角色
+
+
@@ -561,6 +564,19 @@ export default {
this.single = selection.length != 1;
this.multiple = !selection.length;
},
+ // 更多操作触发
+ handleCommand(command, row) {
+ switch (command) {
+ case "handleResetPwd":
+ this.handleResetPwd(row);
+ break;
+ case "handleAuthRole":
+ this.handleAuthRole(row);
+ break;
+ default:
+ break;
+ }
+ },
/** 新增按钮操作 */
handleAdd() {
this.reset();
@@ -603,6 +619,11 @@ export default {
});
}).catch(() => {});
},
+ /** 分配角色操作 */
+ handleAuthRole: function(row) {
+ const userId = row.userId;
+ this.$router.push("/auth/role/" + userId);
+ },
/** 提交按钮 */
submitForm: function() {
this.$refs["form"].validate(valid => {
diff --git a/ruoyi/Dockerfile b/ruoyi/Dockerfile
new file mode 100644
index 000000000..88f4932b6
--- /dev/null
+++ b/ruoyi/Dockerfile
@@ -0,0 +1,14 @@
+FROM anapsix/alpine-java:8_server-jre_unlimited
+
+MAINTAINER Lion Li
+
+RUN mkdir -p /ruoyi/server
+RUN mkdir -p /ruoyi/server/logs
+
+WORKDIR /ruoyi/server
+
+EXPOSE 8080
+
+ADD ./target/ruoyi-admin.jar ./app.jar
+
+ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "app.jar"]
diff --git a/ruoyi/pom.xml b/ruoyi/pom.xml
index d36b6305f..7baca5812 100644
--- a/ruoyi/pom.xml
+++ b/ruoyi/pom.xml
@@ -2,53 +2,18 @@
+
+ ruoyi-vue-plus
+ com.ruoyi
+ 2.5.0
+
4.0.0
-
- com.ruoyi
- ruoyi-vue-plus
- ${ruoyi-vue-plus.version}
-
- RuoYi-Vue-Plus
- https://gitee.com/JavaLionLi/RuoYi-Vue-Plus
- RuoYi-Vue-Plus后台管理系统
-
-
- 2.4.0
- 2.4.7
- UTF-8
- UTF-8
- 1.8
- 3.1.1
- 1.2.6
- 3.0.2
- 4.1.2
- 1.7
- 0.9.1
- 3.4.3
- 5.7.2
- 3.0.3
- 11.0
- 2.4.1
- 3.15.2
- 2.2.1
- 3.4.0
-
-
-
-
-
-
-
- org.springframework.boot
- spring-boot-dependencies
- ${spring-boot.version}
- pom
- import
-
-
-
-
jar
+ ruoyi
+
+
+ web服务入口
+
@@ -87,14 +52,12 @@
com.alibaba
druid-spring-boot-starter
- ${druid.version}
org.apache.velocity
velocity
- ${velocity.version}
@@ -119,7 +82,6 @@
com.github.xiaoymin
knife4j-spring-boot-starter
- ${knife4j.version}
@@ -173,7 +135,6 @@
org.apache.poi
poi-ooxml
- ${poi.version}
@@ -186,7 +147,6 @@
io.jsonwebtoken
jjwt
- ${jwt.version}
@@ -211,23 +171,19 @@
com.baomidou
dynamic-datasource-spring-boot-starter
- ${datasource.version}
com.baomidou
mybatis-plus-boot-starter
- ${mybatis-plus.version}
com.baomidou
mybatis-plus-extension
- ${mybatis-plus.version}
cn.hutool
hutool-all
- ${hutool.version}
@@ -238,24 +194,20 @@
org.springframework.cloud
spring-cloud-starter-openfeign
- ${feign.version}
io.github.openfeign
feign-okhttp
- ${feign-okhttp.version}
de.codecentric
spring-boot-admin-starter-server
- ${spring-boot-admin.version}
de.codecentric
spring-boot-admin-starter-client
- ${spring-boot-admin.version}
@@ -272,12 +224,10 @@
org.redisson
redisson-spring-boot-starter
- ${redisson.version}
com.baomidou
lock4j-redisson-spring-boot-starter
- ${lock4j.version}
@@ -310,118 +260,25 @@
- org.apache.maven.plugins
- maven-compiler-plugin
- 3.1
+ com.spotify
+ docker-maven-plugin
+ ${docker.plugin.version}
- ${java.version}
- ${java.version}
- ${project.build.sourceEncoding}
+ ${docker.namespace}/ruoyi-server:${project.version}
+ ${project.basedir}
+ ${docker.registry.host}
+ ${docker.registry.url}
+ ${docker.registry.url}
+
+
+ /
+ ${project.build.directory}
+ ${project.build.finalName}.jar
+
+
-
-
-
- src/main/resources
-
- true
-
-
-
-
- public
- aliyun nexus
- http://maven.aliyun.com/nexus/content/groups/public/
-
- true
-
-
-
-
-
-
- public
- aliyun nexus
- http://maven.aliyun.com/nexus/content/groups/public/
-
- true
-
-
- false
-
-
-
-
-
-
- local
-
-
- local
- debug
-
-
-
- dev
-
-
- dev
- debug
-
-
-
- true
-
-
-
- prod
-
- prod
- warn
-
-
-
-
-
- jdk8
-
- true
- 1.8
-
-
- 1.8
-
-
-
- jdk11
-
- 11
-
-
- 11
- 3.0.1
-
-
-
-
-
- com.sun.xml.bind
- jaxb-impl
- ${jaxb.version}
-
-
-
-
-
-
- com.sun.xml.bind
- jaxb-impl
-
-
-
-
-
diff --git a/ruoyi/src/main/java/com/ruoyi/common/constant/UserConstants.java b/ruoyi/src/main/java/com/ruoyi/common/constant/UserConstants.java
index 56b46ba83..eda4ab6a8 100644
--- a/ruoyi/src/main/java/com/ruoyi/common/constant/UserConstants.java
+++ b/ruoyi/src/main/java/com/ruoyi/common/constant/UserConstants.java
@@ -2,7 +2,7 @@ package com.ruoyi.common.constant;
/**
* 用户常量信息
- *
+ *
* @author ruoyi
*/
public class UserConstants
@@ -57,6 +57,9 @@ public class UserConstants
/** ParentView组件标识 */
public final static String PARENT_VIEW = "ParentView";
+ /** InnerLink组件标识 */
+ public final static String INNER_LINK = "InnerLink";
+
/** 校验返回结果码 */
public final static String UNIQUE = "0";
public final static String NOT_UNIQUE = "1";
diff --git a/ruoyi/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java b/ruoyi/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java
index 110c5480c..898138b0b 100644
--- a/ruoyi/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java
+++ b/ruoyi/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java
@@ -148,6 +148,10 @@ public class SysUser implements Serializable
@TableField(exist = false)
private Long[] postIds;
+ /** 角色ID */
+ @TableField(exist = false)
+ private Long roleId;
+
public SysUser(Long userId)
{
this.userId = userId;
diff --git a/ruoyi/src/main/java/com/ruoyi/common/core/mybatisplus/cache/MybatisPlusRedisCache.java b/ruoyi/src/main/java/com/ruoyi/common/core/mybatisplus/cache/MybatisPlusRedisCache.java
index 0e21d70ef..633a0b5ab 100644
--- a/ruoyi/src/main/java/com/ruoyi/common/core/mybatisplus/cache/MybatisPlusRedisCache.java
+++ b/ruoyi/src/main/java/com/ruoyi/common/core/mybatisplus/cache/MybatisPlusRedisCache.java
@@ -15,6 +15,9 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* mybatis-redis 二级缓存
*
+ * 使用方法 配置文件开启 mybatis-plus 二级缓存
+ * 在 XxxMapper.java 类上添加注解 @CacheNamespace(implementation = MybatisPlusRedisCache.class, eviction = MybatisPlusRedisCache.class)
+ *
* @author Lion Li
*/
@Slf4j
diff --git a/ruoyi/src/main/java/com/ruoyi/common/core/mybatisplus/methods/InsertAll.java b/ruoyi/src/main/java/com/ruoyi/common/core/mybatisplus/methods/InsertAll.java
index 9c8c0f745..ec57621b8 100644
--- a/ruoyi/src/main/java/com/ruoyi/common/core/mybatisplus/methods/InsertAll.java
+++ b/ruoyi/src/main/java/com/ruoyi/common/core/mybatisplus/methods/InsertAll.java
@@ -1,13 +1,17 @@
package com.ruoyi.common.core.mybatisplus.methods;
import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.core.enums.SqlMethod;
+import com.baomidou.mybatisplus.core.injector.AbstractMethod;
+import com.baomidou.mybatisplus.core.metadata.TableInfo;
+import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
+import org.apache.ibatis.executor.keygen.Jdbc3KeyGenerator;
+import org.apache.ibatis.executor.keygen.KeyGenerator;
import org.apache.ibatis.executor.keygen.NoKeyGenerator;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlSource;
-import com.baomidou.mybatisplus.core.injector.AbstractMethod;
-import com.baomidou.mybatisplus.core.metadata.TableInfo;
-
/**
* 单sql批量插入
*
@@ -20,9 +24,28 @@ public class InsertAll extends AbstractMethod {
final String sql = "";
final String fieldSql = prepareFieldSql(tableInfo);
final String valueSql = prepareValuesSqlForMysqlBatch(tableInfo);
+ KeyGenerator keyGenerator = new NoKeyGenerator();
+ SqlMethod sqlMethod = SqlMethod.INSERT_ONE;
+ String keyProperty = null;
+ String keyColumn = null;
+ // 表包含主键处理逻辑,如果不包含主键当普通字段处理
+ if (StrUtil.isNotBlank(tableInfo.getKeyProperty())) {
+ if (tableInfo.getIdType() == IdType.AUTO) {
+ /** 自增主键 */
+ keyGenerator = new Jdbc3KeyGenerator();
+ keyProperty = tableInfo.getKeyProperty();
+ keyColumn = tableInfo.getKeyColumn();
+ } else {
+ if (null != tableInfo.getKeySequence()) {
+ keyGenerator = TableInfoHelper.genKeyGenerator(getMethod(sqlMethod), tableInfo, builderAssistant);
+ keyProperty = tableInfo.getKeyProperty();
+ keyColumn = tableInfo.getKeyColumn();
+ }
+ }
+ }
final String sqlResult = String.format(sql, tableInfo.getTableName(), fieldSql, valueSql);
SqlSource sqlSource = languageDriver.createSqlSource(configuration, sqlResult, modelClass);
- return this.addInsertMappedStatement(mapperClass, modelClass, "insertAll", sqlSource, new NoKeyGenerator(), null, null);
+ return this.addInsertMappedStatement(mapperClass, modelClass, "insertAll", sqlSource, keyGenerator, keyProperty, keyColumn);
}
private String prepareFieldSql(TableInfo tableInfo) {
diff --git a/ruoyi/src/main/java/com/ruoyi/common/core/redis/RedisCache.java b/ruoyi/src/main/java/com/ruoyi/common/core/redis/RedisCache.java
index 3c8bc9233..f46a21576 100644
--- a/ruoyi/src/main/java/com/ruoyi/common/core/redis/RedisCache.java
+++ b/ruoyi/src/main/java/com/ruoyi/common/core/redis/RedisCache.java
@@ -205,9 +205,9 @@ public class RedisCache {
* @param hKeys Hash键集合
* @return Hash对象集合
*/
- public List getMultiCacheMapValue(final String key, final Collection