Author SHA1 Message Date
odboy 98830dfdc7 !7 !6 chore(version): 更新项目版本号从1.5.0到1.5.2
Merge pull request !7 from Odboy/master
2026-01-17 02:20:15 +00:00
odboy b0a57c778b !5 !4 fix(test): 修复测试类中对象实例化错误
Merge pull request !5 from Odboy/master
2026-01-17 02:11:24 +00:00
230 changed files with 6328 additions and 3438 deletions
+1
View File
@@ -118,3 +118,4 @@
- cutejava-framework:系统基础框架。提供核心功能,如:权限、数据权限、异常处理、缓存、工具类、接口限流、接口防重、接口幂等。 - cutejava-framework:系统基础框架。提供核心功能,如:权限、数据权限、异常处理、缓存、工具类、接口限流、接口防重、接口幂等。
- cutejava-module-system:系统功能模块。提供用户、角色、菜单、部门、岗位、字典、定时任务、邮件、Minio存储、服务监控等功能 - cutejava-module-system:系统功能模块。提供用户、角色、菜单、部门、岗位、字典、定时任务、邮件、Minio存储、服务监控等功能
- cutejava-module-task:串行任务模块,已实现流水线功能。参考阿里云云效,提供流水线功能,可配置流水线任务,并支持任务依赖、任务参数、任务参数校验、任务参数回填。
+4
View File
@@ -45,3 +45,7 @@ npm run build:prod
2、加速node-sass安装 2、加速node-sass安装
https://www.ydyno.com/archives/1219.html https://www.ydyno.com/archives/1219.html
#### 特别鸣谢
- 感谢 [elunez](https://github.com/elunez/eladmin-mp) 大佬提供的基础框架
-7
View File
@@ -34,13 +34,6 @@ export function listMenuByPid(pid) {
}) })
} }
export function listRoleMenuByPid(pid) {
return request({
url: 'api/menu/listRoleMenuByPid?pid=' + pid,
method: 'post'
})
}
export function searchMenu(params) { export function searchMenu(params) {
return request({ return request({
url: 'api/menu/searchMenu', url: 'api/menu/searchMenu',
@@ -1,100 +0,0 @@
// 科技现代:极光幻境(梦幻唯美)
// base color
$blue: #6C5CE7;
$light-blue: #A29BFE;
$red: #FF7675;
$pink: #FD79A8;
$green: #00B894;
$tiffany: #81ECEC;
$yellow: #FFEAA7;
$panGreen: #00B894;
// sidebar
$menuText: #B2BEC3;
$menuActiveText: #A29BFE;
$subMenuActiveText: #FFFFFF;
$menuBg: #0F0F1F;
$menuHover: #1A1A35;
$subMenuBg: #14142A;
$subMenuHover: #2C2C5A;
// 左侧菜单栏宽度
$sideBarWidth: 250px;
// ===== Navbar 顶部导航栏样式变量 =====
// Navbar 背景渐变色(从深靛蓝过渡到深紫蓝色)
$navbarBgStart: $menuBg;
$navbarBgEnd: #0A0A18;
// Navbar 阴影颜色和透明度
$navbarShadowColor: rgba(162, 155, 254, 0.18);
$navbarShadowY: 2px;
$navbarShadowBlur: 8px;
$navbarShadowSpread: 0px;
// Navbar 底部边框颜色和透明度
$navbarBorderColor: rgba(162, 155, 254, 0.25);
$navbarBorderWidth: 1px;
// Navbar 悬停背景色(hamburger 和右侧菜单项)
$navbarHoverBg: rgba(162, 155, 254, 0.1);
// 右侧菜单项文字颜色
$navbarRightMenuColor: $menuText;
// 右侧菜单项悬停效果颜色
$navbarRightMenuHoverColor: $menuActiveText;
$navbarRightMenuHoverGlow: rgba(162, 155, 254, 0.32);
// 头像边框颜色
$navbarAvatarBorderColor: rgba(162, 155, 254, 0.3);
$navbarAvatarHoverBorderColor: $menuActiveText;
$navbarAvatarHoverGlow: rgba(162, 155, 254, 0.42);
// 下拉箭头颜色
$navbarCaretColor: $menuText;
// ===== Hamburger 汉堡菜单按钮样式变量 =====
// Hamburger 默认颜色
$hamburgerColor: $menuText;
// Hamburger 激活状态颜色
$hamburgerActiveColor: $menuActiveText;
// Hamburger 发光效果
$hamburgerGlow: 0 0 6px rgba(162, 155, 254, 0.45);
// ===== Breadcrumb 面包屑导航样式变量 =====
// Breadcrumb 文字颜色
$breadcrumbTextColor: #F0F1F8;
// Breadcrumb 链接颜色(可点击项)
$breadcrumbLinkColor: #F0F1F8;
// Breadcrumb 发光效果
$breadcrumbTextGlow: rgba(162, 155, 254, 0.18);
// Breadcrumb 悬停颜色
$breadcrumbHoverColor: $menuActiveText;
// Breadcrumb 悬停发光效果
$breadcrumbHoverGlow: 0 0 6px rgba(162, 155, 254, 0.4);
// Breadcrumb 分隔符颜色
$breadcrumbSeparatorColor: rgba(129, 236, 236, 0.55);
// Breadcrumb 当前页面文字颜色(不可点击项)
$breadcrumbNoRedirectColor: #F7F8FC;
// the :export directive is the magic sauce for webpack
// https://www.bluematador.com/blog/how-to-share-variables-between/js-and-sass
:export {
menuText: $menuText;
menuActiveText: $menuActiveText;
subMenuActiveText: $subMenuActiveText;
menuBg: $menuBg;
menuHover: $menuHover;
subMenuBg: $subMenuBg;
subMenuHover: $subMenuHover;
sideBarWidth: $sideBarWidth;
}
@@ -1,100 +0,0 @@
// 赛博橙(热情奔放)
// base color
$blue: #FF5722;
$light-blue: #FF7043;
$red: #FF1744;
$pink: #FF4081;
$green: #00E676;
$tiffany: #69F0AE;
$yellow: #FFD600;
$panGreen: #00E676;
// sidebar
$menuText: #FFCCBC;
$menuActiveText: #FF6D00;
$subMenuActiveText: #FFFFFF;
$menuBg: #261411;
$menuHover: #3D1F1A;
$subMenuBg: #1E0D0B;
$subMenuHover: #502620;
// 左侧菜单栏宽度
$sideBarWidth: 250px;
// ===== Navbar 顶部导航栏样式变量 =====
// Navbar 背景渐变色
$navbarBgStart: $menuBg;
$navbarBgEnd: #1A0E0C;
// Navbar 阴影颜色和透明度
$navbarShadowColor: rgba(255, 109, 0, 0.25);
$navbarShadowY: 2px;
$navbarShadowBlur: 8px;
$navbarShadowSpread: 0px;
// Navbar 底部边框颜色和透明度
$navbarBorderColor: rgba(255, 109, 0, 0.35);
$navbarBorderWidth: 1px;
// Navbar 悬停背景色(hamburger 和右侧菜单项)
$navbarHoverBg: rgba(255, 109, 0, 0.12);
// 右侧菜单项文字颜色
$navbarRightMenuColor: #FFD0BC;
// 右侧菜单项悬停效果颜色
$navbarRightMenuHoverColor: $menuActiveText;
$navbarRightMenuHoverGlow: rgba(255, 109, 0, 0.4);
// 头像边框颜色
$navbarAvatarBorderColor: rgba(255, 109, 0, 0.4);
$navbarAvatarHoverBorderColor: $menuActiveText;
$navbarAvatarHoverGlow: rgba(255, 109, 0, 0.5);
// 下拉箭头颜色
$navbarCaretColor: #FFCCBC;
// ===== Hamburger 汉堡菜单按钮样式变量 =====
// Hamburger 默认颜色
$hamburgerColor: #FFCCBC;
// Hamburger 激活状态颜色
$hamburgerActiveColor: $menuActiveText;
// Hamburger 发光效果
$hamburgerGlow: 0 0 8px rgba(255, 109, 0, 0.5);
// ===== Breadcrumb 面包屑导航样式变量 =====
// Breadcrumb 文字颜色
$breadcrumbTextColor: #FFFFFF;
// Breadcrumb 链接颜色(可点击项)
$breadcrumbLinkColor: #FFFFFF;
// Breadcrumb 发光效果
$breadcrumbTextGlow: rgba(255, 109, 0, 0.18);
// Breadcrumb 悬停颜色
$breadcrumbHoverColor: $menuActiveText;
// Breadcrumb 悬停发光效果
$breadcrumbHoverGlow: 0 0 8px rgba(255, 109, 0, 0.5);
// Breadcrumb 分隔符颜色
$breadcrumbSeparatorColor: rgba(255, 64, 129, 0.6);
// Breadcrumb 当前页面文字颜色(不可点击项)
$breadcrumbNoRedirectColor: #FFFFFF;
// the :export directive is the magic sauce for webpack
// https://www.bluematador.com/blog/how-to-share-variables-between/js-and-sass
:export {
menuText: $menuText;
menuActiveText: $menuActiveText;
subMenuActiveText: $subMenuActiveText;
menuBg: $menuBg;
menuHover: $menuHover;
subMenuBg: $subMenuBg;
subMenuHover: $subMenuHover;
sideBarWidth: $sideBarWidth;
}
@@ -1,100 +0,0 @@
// 默认风格
// base color
$blue: #324157;
$light-blue: #3A71A8;
$red: #C03639;
$pink: #E65D6E;
$green: #30B08F;
$tiffany: #4AB7BD;
$yellow: #FEC171;
$panGreen: #30B08F;
// sidebar 默认
$menuText: #bfcbd9;
$menuActiveText: #409EFF;
$subMenuActiveText: #f4f4f5; // https://github.com/ElemeFE/element/issues/12951
$menuBg: #304156;
$menuHover: #263445;
$subMenuBg: #1f2d3d;
$subMenuHover: #001528;
// 左侧菜单栏宽度
$sideBarWidth: 250px;
// ===== Navbar 顶部导航栏样式变量 =====
// Navbar 背景渐变色(从侧边栏颜色过渡到深蓝色)
$navbarBgStart: $menuBg;
$navbarBgEnd: #263445;
// Navbar 阴影颜色和透明度
$navbarShadowColor: rgba(0, 21, 41, 0.15);
$navbarShadowY: 1px;
$navbarShadowBlur: 4px;
$navbarShadowSpread: 0px;
// Navbar 底部边框颜色和透明度
$navbarBorderColor: rgba(0, 21, 41, 0.2);
$navbarBorderWidth: 1px;
// Navbar 悬停背景色(hamburger 和右侧菜单项)
$navbarHoverBg: rgba(0, 0, 0, 0.025);
// 右侧菜单项文字颜色
$navbarRightMenuColor: #5a5e66;
// 右侧菜单项悬停效果颜色
$navbarRightMenuHoverColor: $menuActiveText;
$navbarRightMenuHoverGlow: transparent;
// 头像边框颜色
$navbarAvatarBorderColor: transparent;
$navbarAvatarHoverBorderColor: transparent;
$navbarAvatarHoverGlow: transparent;
// 下拉箭头颜色
$navbarCaretColor: #5a5e66;
// ===== Hamburger 汉堡菜单按钮样式变量 =====
// Hamburger 默认颜色
$hamburgerColor: $menuText;
// Hamburger 激活状态颜色
$hamburgerActiveColor: $menuActiveText;
// Hamburger 发光效果
$hamburgerGlow: transparent;
// ===== Breadcrumb 面包屑导航样式变量 =====
// Breadcrumb 文字颜色
$breadcrumbTextColor: #97a8be;
// Breadcrumb 链接颜色(可点击项)
$breadcrumbLinkColor: #97a8be;
// Breadcrumb 发光效果
$breadcrumbTextGlow: transparent;
// Breadcrumb 悬停颜色
$breadcrumbHoverColor: $menuActiveText;
// Breadcrumb 悬停发光效果
$breadcrumbHoverGlow: transparent;
// Breadcrumb 分隔符颜色
$breadcrumbSeparatorColor: #97a8be;
// Breadcrumb 当前页面文字颜色(不可点击项)
$breadcrumbNoRedirectColor: #97a8be;
// the :export directive is the magic sauce for webpack
// https://www.bluematador.com/blog/how-to-share-variables-between/js-and-sass
:export {
menuText: $menuText;
menuActiveText: $menuActiveText;
subMenuActiveText: $subMenuActiveText;
menuBg: $menuBg;
menuHover: $menuHover;
subMenuBg: $subMenuBg;
subMenuHover: $subMenuHover;
sideBarWidth: $sideBarWidth;
}
@@ -1,101 +0,0 @@
// 专业稳重(一般)
// base color
$blue: #3A71A8;
$light-blue: #5A9BDB;
$red: #D5657A;
$pink: #E696A5;
$green: #4AB7BD;
$tiffany: #6BCFD5;
$yellow: #FFD166;
$panGreen: #4AB7BD;
// sidebar
$menuText: #C0C9D5;
$menuActiveText: #FFFFFF;
$subMenuActiveText: #409EFF;
$menuBg: #234781;
$menuHover: #1D3A6B;
$subMenuBg: #152B4F;
$subMenuHover: #2D5BA6;
// 左侧菜单栏宽度
$sideBarWidth: 250px;
// ===== Navbar 顶部导航栏样式变量 =====
// Navbar 背景渐变色(从侧边栏颜色过渡到深蓝色)
$navbarBgStart: $menuBg;
$navbarBgEnd: #1A3055;
// Navbar 阴影颜色和透明度
$navbarShadowColor: rgba(58, 113, 168, 0.2);
$navbarShadowY: 2px;
$navbarShadowBlur: 8px;
$navbarShadowSpread: 0px;
// Navbar 底部边框颜色和透明度
$navbarBorderColor: rgba(90, 155, 219, 0.3);
$navbarBorderWidth: 1px;
// Navbar 悬停背景色(hamburger 和右侧菜单项)
$navbarHoverBg: rgba(90, 155, 219, 0.15);
// 右侧菜单项文字颜色
$navbarRightMenuColor: $menuText;
// 右侧菜单项悬停效果颜色
$navbarRightMenuHoverColor: $menuActiveText;
$navbarRightMenuHoverGlow: rgba(90, 155, 219, 0.3);
// 头像边框颜色
$navbarAvatarBorderColor: rgba(90, 155, 219, 0.3);
$navbarAvatarHoverBorderColor: $light-blue;
$navbarAvatarHoverGlow: rgba(90, 155, 219, 0.4);
// 下拉箭头颜色
$navbarCaretColor: $menuText;
// ===== Hamburger 汉堡菜单按钮样式变量 =====
// Hamburger 默认颜色
$hamburgerColor: $menuText;
// Hamburger 激活状态颜色
$hamburgerActiveColor: $menuActiveText;
// Hamburger 发光效果
$hamburgerGlow: 0 0 6px rgba(90, 155, 219, 0.3);
// ===== Breadcrumb 面包屑导航样式变量 =====
// Breadcrumb 文字颜色
$breadcrumbTextColor: #F0F4F8;
// Breadcrumb 链接颜色(可点击项)
$breadcrumbLinkColor: #F0F4F8;
// Breadcrumb 发光效果
$breadcrumbTextGlow: rgba(90, 155, 219, 0.2);
// Breadcrumb 悬停颜色
$breadcrumbHoverColor: $light-blue;
// Breadcrumb 悬停发光效果
$breadcrumbHoverGlow: 0 0 6px rgba(90, 155, 219, 0.3);
// Breadcrumb 分隔符颜色
$breadcrumbSeparatorColor: rgba(90, 155, 219, 0.4);
// Breadcrumb 当前页面文字颜色(不可点击项)
$breadcrumbNoRedirectColor: #F5F8FC;
// the :export directive is the magic sauce for webpack
// https://www.bluematador.com/blog/how-to-share-variables-between-js-and-sass
:export {
menuText: $menuText;
menuActiveText: $menuActiveText;
subMenuActiveText: $subMenuActiveText;
menuBg: $menuBg;
menuHover: $menuHover;
subMenuBg: $subMenuBg;
subMenuHover: $subMenuHover;
sideBarWidth: $sideBarWidth;
}
@@ -1,100 +0,0 @@
// 科技现代:太阳耀斑(热烈活力)
// base color
$blue: #FF6B35;
$light-blue: #FF8C42;
$red: #E84C5B;
$pink: #FF7B9C;
$green: #FFC857;
$tiffany: #FF9F45;
$yellow: #FFD93D;
$panGreen: #FFC857;
// sidebar
$menuText: #D4A574;
$menuActiveText: #FF8C42;
$subMenuActiveText: #FFFFFF;
$menuBg: #1A1512;
$menuHover: #2A221D;
$subMenuBg: #221E1A;
$subMenuHover: #3D332C;
// 左侧菜单栏宽度
$sideBarWidth: 250px;
// ===== Navbar 顶部导航栏样式变量 =====
// Navbar 背景渐变色(从深棕色过渡到炭黑色)
$navbarBgStart: $menuBg;
$navbarBgEnd: #15100D;
// Navbar 阴影颜色和透明度
$navbarShadowColor: rgba(255, 140, 66, 0.2);
$navbarShadowY: 2px;
$navbarShadowBlur: 8px;
$navbarShadowSpread: 0px;
// Navbar 底部边框颜色和透明度
$navbarBorderColor: rgba(255, 140, 66, 0.25);
$navbarBorderWidth: 1px;
// Navbar 悬停背景色(hamburger 和右侧菜单项)
$navbarHoverBg: rgba(255, 140, 66, 0.1);
// 右侧菜单项文字颜色
$navbarRightMenuColor: $menuText;
// 右侧菜单项悬停效果颜色
$navbarRightMenuHoverColor: $menuActiveText;
$navbarRightMenuHoverGlow: rgba(255, 140, 66, 0.3);
// 头像边框颜色
$navbarAvatarBorderColor: rgba(255, 140, 66, 0.3);
$navbarAvatarHoverBorderColor: $menuActiveText;
$navbarAvatarHoverGlow: rgba(255, 140, 66, 0.45);
// 下拉箭头颜色
$navbarCaretColor: $menuText;
// ===== Hamburger 汉堡菜单按钮样式变量 =====
// Hamburger 默认颜色
$hamburgerColor: $menuText;
// Hamburger 激活状态颜色
$hamburgerActiveColor: $menuActiveText;
// Hamburger 发光效果
$hamburgerGlow: 0 0 6px rgba(255, 140, 66, 0.4);
// ===== Breadcrumb 面包屑导航样式变量 =====
// Breadcrumb 文字颜色
$breadcrumbTextColor: #FDF6EC;
// Breadcrumb 链接颜色(可点击项)
$breadcrumbLinkColor: #FDF6EC;
// Breadcrumb 发光效果
$breadcrumbTextGlow: rgba(255, 140, 66, 0.15);
// Breadcrumb 悬停颜色
$breadcrumbHoverColor: $menuActiveText;
// Breadcrumb 悬停发光效果
$breadcrumbHoverGlow: 0 0 6px rgba(255, 140, 66, 0.35);
// Breadcrumb 分隔符颜色
$breadcrumbSeparatorColor: rgba(255, 159, 69, 0.5);
// Breadcrumb 当前页面文字颜色(不可点击项)
$breadcrumbNoRedirectColor: #FFF9F0;
// the :export directive is the magic sauce for webpack
// https://www.bluematador.com/blog/how-to-share-variables-between/js-and-sass
:export {
menuText: $menuText;
menuActiveText: $menuActiveText;
subMenuActiveText: $subMenuActiveText;
menuBg: $menuBg;
menuHover: $menuHover;
subMenuBg: $subMenuBg;
subMenuHover: $subMenuHover;
sideBarWidth: $sideBarWidth;
}
@@ -1,101 +0,0 @@
// 科技现代:深空极客(好看)
// base color
$blue: #4A90E2;
$light-blue: #66CCFF;
$red: #FF6B6B;
$pink: #FF9E9E;
$green: #66FFCC;
$tiffany: #81D8D0;
$yellow: #FFD93D;
$panGreen: #66FFCC;
// sidebar
$menuText: #A0AABF;
$menuActiveText: #66FFCC;
$subMenuActiveText: #FFFFFF;
$menuBg: #0F1520;
$menuHover: #1C2430;
$subMenuBg: #1A2332;
$subMenuHover: #2A3B5C;
// 左侧菜单栏宽度
$sideBarWidth: 250px;
// ===== Navbar 顶部导航栏样式变量 =====
// Navbar 背景渐变色(从侧边栏颜色过渡到深蓝色)
$navbarBgStart: $menuBg;
$navbarBgEnd: #162035;
// Navbar 阴影颜色和透明度
$navbarShadowColor: rgba(74, 144, 226, 0.15);
$navbarShadowY: 2px;
$navbarShadowBlur: 8px;
$navbarShadowSpread: 0px;
// Navbar 底部边框颜色和透明度
$navbarBorderColor: rgba(74, 144, 226, 0.2);
$navbarBorderWidth: 1px;
// Navbar 悬停背景色(hamburger 和右侧菜单项)
$navbarHoverBg: rgba(74, 144, 226, 0.1);
// 右侧菜单项文字颜色
$navbarRightMenuColor: $menuText;
// 右侧菜单项悬停效果颜色
$navbarRightMenuHoverColor: $menuActiveText;
$navbarRightMenuHoverGlow: rgba(102, 255, 204, 0.3);
// 头像边框颜色
$navbarAvatarBorderColor: rgba(102, 255, 204, 0.3);
$navbarAvatarHoverBorderColor: $menuActiveText;
$navbarAvatarHoverGlow: rgba(102, 255, 204, 0.4);
// 下拉箭头颜色
$navbarCaretColor: $menuText;
// ===== Hamburger 汉堡菜单按钮样式变量 =====
// Hamburger 默认颜色
$hamburgerColor: $menuText;
// Hamburger 激活状态颜色
$hamburgerActiveColor: $menuActiveText;
// Hamburger 发光效果
$hamburgerGlow: 0 0 6px $menuActiveText;
// ===== Breadcrumb 面包屑导航样式变量 =====
// Breadcrumb 文字颜色
$breadcrumbTextColor: #FFFFFF;
// Breadcrumb 链接颜色(可点击项)
$breadcrumbLinkColor: #FFFFFF;
// Breadcrumb 发光效果
$breadcrumbTextGlow: rgba(102, 255, 204, 0.3);
// Breadcrumb 悬停颜色
$breadcrumbHoverColor: $menuActiveText;
// Breadcrumb 悬停发光效果
$breadcrumbHoverGlow: 0 0 6px rgba(102, 255, 204, 0.4);
// Breadcrumb 分隔符颜色
$breadcrumbSeparatorColor: rgba(102, 255, 204, 0.5);
// Breadcrumb 当前页面文字颜色(不可点击项)
$breadcrumbNoRedirectColor: #FFFFFF;
// the :export directive is the magic sauce for webpack
// https://www.bluematador.com/blog/how-to-share-variables-between-js-and-sass
:export {
menuText: $menuText;
menuActiveText: $menuActiveText;
subMenuActiveText: $subMenuActiveText;
menuBg: $menuBg;
menuHover: $menuHover;
subMenuBg: $subMenuBg;
subMenuHover: $subMenuHover;
sideBarWidth: $sideBarWidth;
}
@@ -1,101 +0,0 @@
// 科技现代:赛博蓝光(好看)
// base color
$blue: #4FC3F7;
$light-blue: #81D4FA;
$red: #FF8A80;
$pink: #FFB3B8;
$green: #80DEEA;
$tiffany: #81D4FA;
$yellow: #FFD54F;
$panGreen: #80DEEA;
// sidebar
$menuText: #B0B8D0;
$menuActiveText: #4FC3F7;
$subMenuActiveText: #FFFFFF;
$menuBg: #0A0E17;
$menuHover: #151A2A;
$subMenuBg: #12182D;
$subMenuHover: #1E3A8A;
// 左侧菜单栏宽度
$sideBarWidth: 250px;
// ===== Navbar 顶部导航栏样式变量 =====
// Navbar 背景渐变色(从侧边栏颜色过渡到深蓝紫色)
$navbarBgStart: $menuBg;
$navbarBgEnd: #0D1422;
// Navbar 阴影颜色和透明度
$navbarShadowColor: rgba(79, 195, 247, 0.15);
$navbarShadowY: 2px;
$navbarShadowBlur: 8px;
$navbarShadowSpread: 0px;
// Navbar 底部边框颜色和透明度
$navbarBorderColor: rgba(79, 195, 247, 0.2);
$navbarBorderWidth: 1px;
// Navbar 悬停背景色(hamburger 和右侧菜单项)
$navbarHoverBg: rgba(79, 195, 247, 0.1);
// 右侧菜单项文字颜色
$navbarRightMenuColor: $menuText;
// 右侧菜单项悬停效果颜色
$navbarRightMenuHoverColor: $menuActiveText;
$navbarRightMenuHoverGlow: rgba(79, 195, 247, 0.3);
// 头像边框颜色
$navbarAvatarBorderColor: rgba(79, 195, 247, 0.3);
$navbarAvatarHoverBorderColor: $menuActiveText;
$navbarAvatarHoverGlow: rgba(79, 195, 247, 0.4);
// 下拉箭头颜色
$navbarCaretColor: $menuText;
// ===== Hamburger 汉堡菜单按钮样式变量 =====
// Hamburger 默认颜色
$hamburgerColor: $menuText;
// Hamburger 激活状态颜色
$hamburgerActiveColor: $menuActiveText;
// Hamburger 发光效果
$hamburgerGlow: 0 0 6px $menuActiveText;
// ===== Breadcrumb 面包屑导航样式变量 =====
// Breadcrumb 文字颜色
$breadcrumbTextColor: #FFFFFF;
// Breadcrumb 链接颜色(可点击项)
$breadcrumbLinkColor: #FFFFFF;
// Breadcrumb 发光效果
$breadcrumbTextGlow: rgba(79, 195, 247, 0.2);
// Breadcrumb 悬停颜色
$breadcrumbHoverColor: $menuActiveText;
// Breadcrumb 悬停发光效果
$breadcrumbHoverGlow: 0 0 6px rgba(79, 195, 247, 0.4);
// Breadcrumb 分隔符颜色
$breadcrumbSeparatorColor: rgba(79, 195, 247, 0.5);
// Breadcrumb 当前页面文字颜色(不可点击项)
$breadcrumbNoRedirectColor: #FFFFFF;
// the :export directive is the magic sauce for webpack
// https://www.bluematador.com/blog/how-to-share-variables-between-js-and-sass
:export {
menuText: $menuText;
menuActiveText: $menuActiveText;
subMenuActiveText: $subMenuActiveText;
menuBg: $menuBg;
menuHover: $menuHover;
subMenuBg: $subMenuBg;
subMenuHover: $subMenuHover;
sideBarWidth: $sideBarWidth;
}
@@ -1,101 +0,0 @@
// 科技现代:钛银脉冲(好看)
// base color
$blue: #393E7C;
$light-blue: #4A50A0;
$red: #E84C5B;
$pink: #FF7B9C;
$green: #4AB7BD;
$tiffany: #64D2FF;
$yellow: #FFD166;
$panGreen: #4AB7BD;
// sidebar
$menuText: #CCCCCC;
$menuActiveText: #00E5FF;
$subMenuActiveText: #FFFFFF;
$menuBg: #1A1A2E;
$menuHover: #222244;
$subMenuBg: #252545;
$subMenuHover: #393E7C;
// 左侧菜单栏宽度
$sideBarWidth: 250px;
// ===== Navbar 顶部导航栏样式变量 =====
// Navbar 背景渐变色(从侧边栏颜色过渡到深紫色)
$navbarBgStart: $menuBg;
$navbarBgEnd: #141426;
// Navbar 阴影颜色和透明度
$navbarShadowColor: rgba(0, 229, 255, 0.15);
$navbarShadowY: 2px;
$navbarShadowBlur: 8px;
$navbarShadowSpread: 0px;
// Navbar 底部边框颜色和透明度
$navbarBorderColor: rgba(0, 229, 255, 0.2);
$navbarBorderWidth: 1px;
// Navbar 悬停背景色(hamburger 和右侧菜单项)
$navbarHoverBg: rgba(0, 229, 255, 0.1);
// 右侧菜单项文字颜色
$navbarRightMenuColor: $menuText;
// 右侧菜单项悬停效果颜色
$navbarRightMenuHoverColor: $menuActiveText;
$navbarRightMenuHoverGlow: rgba(0, 229, 255, 0.3);
// 头像边框颜色
$navbarAvatarBorderColor: rgba(0, 229, 255, 0.3);
$navbarAvatarHoverBorderColor: $menuActiveText;
$navbarAvatarHoverGlow: rgba(0, 229, 255, 0.4);
// 下拉箭头颜色
$navbarCaretColor: $menuText;
// ===== Hamburger 汉堡菜单按钮样式变量 =====
// Hamburger 默认颜色
$hamburgerColor: $menuText;
// Hamburger 激活状态颜色
$hamburgerActiveColor: $menuActiveText;
// Hamburger 发光效果
$hamburgerGlow: 0 0 6px $menuActiveText;
// ===== Breadcrumb 面包屑导航样式变量 =====
// Breadcrumb 文字颜色
$breadcrumbTextColor: #FFFFFF;
// Breadcrumb 链接颜色(可点击项)
$breadcrumbLinkColor: #FFFFFF;
// Breadcrumb 发光效果
$breadcrumbTextGlow: rgba(0, 229, 255, 0.2);
// Breadcrumb 悬停颜色
$breadcrumbHoverColor: $menuActiveText;
// Breadcrumb 悬停发光效果
$breadcrumbHoverGlow: 0 0 6px rgba(0, 229, 255, 0.4);
// Breadcrumb 分隔符颜色
$breadcrumbSeparatorColor: rgba(0, 229, 255, 0.5);
// Breadcrumb 当前页面文字颜色(不可点击项)
$breadcrumbNoRedirectColor: #FFFFFF;
// the :export directive is the magic sauce for webpack
// https://www.bluematador.com/blog/how-to-share-variables-between/js-and-sass
:export {
menuText: $menuText;
menuActiveText: $menuActiveText;
subMenuActiveText: $subMenuActiveText;
menuBg: $menuBg;
menuHover: $menuHover;
subMenuBg: $subMenuBg;
subMenuHover: $subMenuHover;
sideBarWidth: $sideBarWidth;
}
@@ -1,100 +0,0 @@
// 清新明亮:天空云朵(清新舒适)
// base color
$blue: #5BA3F0;
$light-blue: #7BC4FF;
$red: #FF6B8A;
$pink: #FF8FA8;
$green: #6BCB77;
$tiffany: #7FD1AE;
$yellow: #FFD93D;
$panGreen: #6BCB77;
// sidebar
$menuText: #2A3A4A;
$menuActiveText: #2B7BD9;
$subMenuActiveText: #2B7BD9;
$menuBg: #FFFFFF;
$menuHover: #F0F5FF;
$subMenuBg: #F8FAFC;
$subMenuHover: #E1E8F5;
// 左侧菜单栏宽度
$sideBarWidth: 250px;
// ===== Navbar 顶部导航栏样式变量 =====
// Navbar 背景渐变色(从白色过渡到浅蓝)
$navbarBgStart: #FFFFFF;
$navbarBgEnd: #F5F9FF;
// Navbar 阴影颜色和透明度
$navbarShadowColor: rgba(91, 163, 240, 0.15);
$navbarShadowY: 1px;
$navbarShadowBlur: 4px;
$navbarShadowSpread: 0px;
// Navbar 底部边框颜色和透明度
$navbarBorderColor: rgba(91, 163, 240, 0.2);
$navbarBorderWidth: 1px;
// Navbar 悬停背景色(hamburger 和右侧菜单项)
$navbarHoverBg: #F0F5FF;
// 右侧菜单项文字颜色
$navbarRightMenuColor: #5A6C7D;
// 右侧菜单项悬停效果颜色
$navbarRightMenuHoverColor: $menuActiveText;
$navbarRightMenuHoverGlow: rgba(91, 163, 240, 0.2);
// 头像边框颜色
$navbarAvatarBorderColor: rgba(91, 163, 240, 0.25);
$navbarAvatarHoverBorderColor: $menuActiveText;
$navbarAvatarHoverGlow: rgba(91, 163, 240, 0.3);
// 下拉箭头颜色
$navbarCaretColor: #5A6C7D;
// ===== Hamburger 汉堡菜单按钮样式变量 =====
// Hamburger 默认颜色
$hamburgerColor: #5A6C7D;
// Hamburger 激活状态颜色
$hamburgerActiveColor: $menuActiveText;
// Hamburger 发光效果
$hamburgerGlow: 0 0 4px rgba(91, 163, 240, 0.3);
// ===== Breadcrumb 面包屑导航样式变量 =====
// Breadcrumb 文字颜色
$breadcrumbTextColor: #3A4A5A;
// Breadcrumb 链接颜色(可点击项)
$breadcrumbLinkColor: #3A4A5A;
// Breadcrumb 发光效果
$breadcrumbTextGlow: transparent;
// Breadcrumb 悬停颜色
$breadcrumbHoverColor: $menuActiveText;
// Breadcrumb 悬停发光效果
$breadcrumbHoverGlow: transparent;
// Breadcrumb 分隔符颜色
$breadcrumbSeparatorColor: rgba(91, 163, 240, 0.4);
// Breadcrumb 当前页面文字颜色(不可点击项)
$breadcrumbNoRedirectColor: #2A3A4A;
// the :export directive is the magic sauce for webpack
// https://www.bluematador.com/blog/how-to-share-variables-between/js-and-sass
:export {
menuText: $menuText;
menuActiveText: $menuActiveText;
subMenuActiveText: $subMenuActiveText;
menuBg: $menuBg;
menuHover: $menuHover;
subMenuBg: $subMenuBg;
subMenuHover: $subMenuHover;
sideBarWidth: $sideBarWidth;
}
@@ -1,100 +0,0 @@
// 清新明亮:薄荷清新(清爽自然)
// base color
$blue: #5F9EA0;
$light-blue: #7DD3C0;
$red: #FF7F7F;
$pink: #FFA8A8;
$green: #95E1D3;
$tiffany: #B8F2E6;
$yellow: #FFEAA7;
$panGreen: #95E1D3;
// sidebar
$menuText: #3A4A5A;
$menuActiveText: #5F9EA0;
$subMenuActiveText: #5F9EA0;
$menuBg: #FAFEFC;
$menuHover: #F0FAF7;
$subMenuBg: #FCFDFB;
$subMenuHover: #E5F5F0;
// 左侧菜单栏宽度
$sideBarWidth: 250px;
// ===== Navbar 顶部导航栏样式变量 =====
// Navbar 背景渐变色(从白色过渡到淡薄荷色)
$navbarBgStart: #FFFFFF;
$navbarBgEnd: #F5FFFA;
// Navbar 阴影颜色和透明度
$navbarShadowColor: rgba(95, 158, 160, 0.12);
$navbarShadowY: 1px;
$navbarShadowBlur: 4px;
$navbarShadowSpread: 0px;
// Navbar 底部边框颜色和透明度
$navbarBorderColor: rgba(95, 158, 160, 0.15);
$navbarBorderWidth: 1px;
// Navbar 悬停背景色(hamburger 和右侧菜单项)
$navbarHoverBg: #F0FAF7;
// 右侧菜单项文字颜色
$navbarRightMenuColor: #5A6B7A;
// 右侧菜单项悬停效果颜色
$navbarRightMenuHoverColor: $menuActiveText;
$navbarRightMenuHoverGlow: rgba(95, 158, 160, 0.2);
// 头像边框颜色
$navbarAvatarBorderColor: rgba(95, 158, 160, 0.25);
$navbarAvatarHoverBorderColor: $menuActiveText;
$navbarAvatarHoverGlow: rgba(95, 158, 160, 0.3);
// 下拉箭头颜色
$navbarCaretColor: #5A6B7A;
// ===== Hamburger 汉堡菜单按钮样式变量 =====
// Hamburger 默认颜色
$hamburgerColor: #5A6B7A;
// Hamburger 激活状态颜色
$hamburgerActiveColor: $menuActiveText;
// Hamburger 发光效果
$hamburgerGlow: 0 0 4px rgba(95, 158, 160, 0.3);
// ===== Breadcrumb 面包屑导航样式变量 =====
// Breadcrumb 文字颜色
$breadcrumbTextColor: #3A4A5A;
// Breadcrumb 链接颜色(可点击项)
$breadcrumbLinkColor: #3A4A5A;
// Breadcrumb 发光效果
$breadcrumbTextGlow: transparent;
// Breadcrumb 悬停颜色
$breadcrumbHoverColor: $menuActiveText;
// Breadcrumb 悬停发光效果
$breadcrumbHoverGlow: transparent;
// Breadcrumb 分隔符颜色
$breadcrumbSeparatorColor: rgba(90, 107, 122, 0.4);
// Breadcrumb 当前页面文字颜色(不可点击项)
$breadcrumbNoRedirectColor: #2A3A4A;
// the :export directive is the magic sauce for webpack
// https://www.bluematador.com/blog/how-to-share-variables-between/js-and-sass
:export {
menuText: $menuText;
menuActiveText: $menuActiveText;
subMenuActiveText: $subMenuActiveText;
menuBg: $menuBg;
menuHover: $menuHover;
subMenuBg: $subMenuBg;
subMenuHover: $subMenuHover;
sideBarWidth: $sideBarWidth;
}
@@ -1,100 +0,0 @@
// 清新明亮:海风浅蓝(宁静舒适)
// base color
$blue: #4A90E2;
$light-blue: #6BB3FF;
$red: #FF7F7F;
$pink: #FFA3A3;
$green: #7DD3C0;
$tiffany: #9CE6DC;
$yellow: #FFEAA7;
$panGreen: #7DD3C0;
// sidebar
$menuText: #3A4A5A;
$menuActiveText: #4A90E2;
$subMenuActiveText: #4A90E2;
$menuBg: #F5FAFF;
$menuHover: #EBF4FF;
$subMenuBg: #F8FCFF;
$subMenuHover: #D9EBFF;
// 左侧菜单栏宽度
$sideBarWidth: 250px;
// ===== Navbar 顶部导航栏样式变量 =====
// Navbar 背景渐变色(从白色过渡到浅蓝色)
$navbarBgStart: #FFFFFF;
$navbarBgEnd: #F5FAFF;
// Navbar 阴影颜色和透明度
$navbarShadowColor: rgba(74, 144, 226, 0.12);
$navbarShadowY: 1px;
$navbarShadowBlur: 4px;
$navbarShadowSpread: 0px;
// Navbar 底部边框颜色和透明度
$navbarBorderColor: rgba(74, 144, 226, 0.15);
$navbarBorderWidth: 1px;
// Navbar 悬停背景色(hamburger 和右侧菜单项)
$navbarHoverBg: #EBF4FF;
// 右侧菜单项文字颜色
$navbarRightMenuColor: #5A6C7D;
// 右侧菜单项悬停效果颜色
$navbarRightMenuHoverColor: $menuActiveText;
$navbarRightMenuHoverGlow: rgba(74, 144, 226, 0.2);
// 头像边框颜色
$navbarAvatarBorderColor: rgba(74, 144, 226, 0.25);
$navbarAvatarHoverBorderColor: $menuActiveText;
$navbarAvatarHoverGlow: rgba(74, 144, 226, 0.3);
// 下拉箭头颜色
$navbarCaretColor: #5A6C7D;
// ===== Hamburger 汉堡菜单按钮样式变量 =====
// Hamburger 默认颜色
$hamburgerColor: #5A6C7D;
// Hamburger 激活状态颜色
$hamburgerActiveColor: $menuActiveText;
// Hamburger 发光效果
$hamburgerGlow: 0 0 4px rgba(74, 144, 226, 0.3);
// ===== Breadcrumb 面包屑导航样式变量 =====
// Breadcrumb 文字颜色
$breadcrumbTextColor: #3A4A5A;
// Breadcrumb 链接颜色(可点击项)
$breadcrumbLinkColor: #3A4A5A;
// Breadcrumb 发光效果
$breadcrumbTextGlow: transparent;
// Breadcrumb 悬停颜色
$breadcrumbHoverColor: $menuActiveText;
// Breadcrumb 悬停发光效果
$breadcrumbHoverGlow: transparent;
// Breadcrumb 分隔符颜色
$breadcrumbSeparatorColor: rgba(90, 108, 125, 0.4);
// Breadcrumb 当前页面文字颜色(不可点击项)
$breadcrumbNoRedirectColor: #2A3A4A;
// the :export directive is the magic sauce for webpack
// https://www.bluematador.com/blog/how-to-share-variables-between/js-and-sass
:export {
menuText: $menuText;
menuActiveText: $menuActiveText;
subMenuActiveText: $subMenuActiveText;
menuBg: $menuBg;
menuHover: $menuHover;
subMenuBg: $subMenuBg;
subMenuHover: $subMenuHover;
sideBarWidth: $sideBarWidth;
}
@@ -1 +1,36 @@
@import 'themes/light/variables.cloudsky'; // base color
$blue:#324157;
$light-blue:#3A71A8;
$red:#C03639;
$pink: #E65D6E;
$green: #30B08F;
$tiffany: #4AB7BD;
$yellow:#FEC171;
$panGreen: #30B08F;
// sidebar
$menuText:#bfcbd9;
$menuActiveText:#409EFF;
$subMenuActiveText:#f4f4f5; // https://github.com/ElemeFE/element/issues/12951
$menuBg:#304156;
$menuHover:#263445;
$subMenuBg:#1f2d3d;
$subMenuHover:#001528;
// 左侧菜单栏宽度
$sideBarWidth: 250px;
// the :export directive is the magic sauce for webpack
// https://www.bluematador.com/blog/how-to-share-variables-between-js-and-sass
:export {
menuText: $menuText;
menuActiveText: $menuActiveText;
subMenuActiveText: $subMenuActiveText;
menuBg: $menuBg;
menuHover: $menuHover;
subMenuBg: $subMenuBg;
subMenuHover: $subMenuHover;
sideBarWidth: $sideBarWidth;
}
@@ -70,57 +70,15 @@ export default {
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@import "~@/assets/styles/variables";
.app-breadcrumb.el-breadcrumb { .app-breadcrumb.el-breadcrumb {
display: inline-block; display: inline-block;
font-size: 14px; font-size: 14px;
line-height: 50px; line-height: 50px;
margin-left: 8px; margin-left: 8px;
::v-deep .el-breadcrumb__item {
.el-breadcrumb__inner {
color: $breadcrumbTextColor !important;
font-weight: 500;
transition: all 0.3s ease;
&.is-link {
color: $breadcrumbLinkColor !important;
text-shadow: 0 0 4px $breadcrumbTextGlow;
&:hover {
color: $breadcrumbHoverColor !important;
filter: drop-shadow($breadcrumbHoverGlow);
}
}
&:hover {
color: $breadcrumbHoverColor !important;
filter: drop-shadow($breadcrumbHoverGlow);
}
}
.el-breadcrumb__separator {
color: $breadcrumbSeparatorColor;
}
}
a {
color: $breadcrumbLinkColor !important;
font-weight: 500;
text-shadow: 0 0 4px $breadcrumbTextGlow;
&:hover {
color: $breadcrumbHoverColor !important;
filter: drop-shadow($breadcrumbHoverGlow);
}
}
.no-redirect { .no-redirect {
color: $breadcrumbNoRedirectColor !important; color: #97a8be;
cursor: text; cursor: text;
font-weight: 500;
text-shadow: 0 0 4px $breadcrumbTextGlow;
} }
} }
</style> </style>
@@ -1,6 +1,6 @@
<template> <template>
<a <a
href="https://gitee.com/odboy-tianjun/cutejava" href="https://github.com/odboy-tianjun/cutejava"
target="_blank" target="_blank"
class="github-corner" class="github-corner"
aria-label="View source on Github" aria-label="View source on Github"
@@ -32,25 +32,15 @@ export default {
} }
</script> </script>
<style lang="scss" scoped> <style scoped>
@import "~@/assets/styles/variables";
.hamburger { .hamburger {
display: inline-block; display: inline-block;
vertical-align: middle; vertical-align: middle;
width: 20px; width: 20px;
height: 20px; height: 20px;
fill: $hamburgerColor;
transition: all 0.3s ease;
} }
.hamburger.is-active { .hamburger.is-active {
transform: rotate(180deg); transform: rotate(180deg);
fill: $hamburgerActiveColor;
filter: drop-shadow($hamburgerGlow);
}
.hamburger:hover {
fill: $hamburgerActiveColor;
} }
</style> </style>
+13 -34
View File
@@ -12,9 +12,10 @@
<screenfull id="screenfull" class="right-menu-item hover-effect" /> <screenfull id="screenfull" class="right-menu-item hover-effect" />
</el-tooltip> </el-tooltip>
<!--<el-tooltip content="布局设置" effect="dark" placement="bottom">--> <el-tooltip content="布局设置" effect="dark" placement="bottom">
<!-- <size-select id="size-select" class="right-menu-item hover-effect" />--> <size-select id="size-select" class="right-menu-item hover-effect" />
<!--</el-tooltip>--> </el-tooltip>
</template> </template>
<el-dropdown class="avatar-container right-menu-item hover-effect" trigger="click"> <el-dropdown class="avatar-container right-menu-item hover-effect" trigger="click">
@@ -49,7 +50,7 @@ import { mapGetters } from 'vuex'
import Breadcrumb from '@/components/Breadcrumb' import Breadcrumb from '@/components/Breadcrumb'
import Hamburger from '@/components/Hamburger' import Hamburger from '@/components/Hamburger'
import Screenfull from '@/components/Screenfull' import Screenfull from '@/components/Screenfull'
// import SizeSelect from '@/components/SizeSelect' import SizeSelect from '@/components/SizeSelect'
import Search from '@/components/HeaderSearch' import Search from '@/components/HeaderSearch'
import Avatar from '@/assets/images/avatar.png' import Avatar from '@/assets/images/avatar.png'
@@ -58,7 +59,7 @@ export default {
Breadcrumb, Breadcrumb,
Hamburger, Hamburger,
Screenfull, Screenfull,
// SizeSelect, SizeSelect,
Search Search
}, },
data() { data() {
@@ -109,30 +110,23 @@ export default {
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@import "~@/assets/styles/variables";
.navbar { .navbar {
height: 50px; height: 50px;
overflow: hidden; overflow: hidden;
position: relative; position: relative;
background: linear-gradient(90deg, $navbarBgStart 0%, $navbarBgEnd 100%); background: #fff;
box-shadow: 0 $navbarShadowY $navbarShadowBlur $navbarShadowSpread $navbarShadowColor; box-shadow: 0 1px 4px rgba(0,21,41,.08);
border-bottom: $navbarBorderWidth solid $navbarBorderColor;
.hamburger-container { .hamburger-container {
line-height: 46px; line-height: 46px;
height: 100%; height: 100%;
float: left; float: left;
cursor: pointer; cursor: pointer;
transition: all 0.3s ease; transition: background .3s;
-webkit-tap-highlight-color:transparent; -webkit-tap-highlight-color:transparent;
&:hover { &:hover {
background: $navbarHoverBg; background: rgba(0, 0, 0, .025)
.hamburger {
color: $menuActiveText;
filter: drop-shadow($hamburgerGlow);
}
} }
} }
@@ -159,17 +153,15 @@ export default {
padding: 0 8px; padding: 0 8px;
height: 100%; height: 100%;
font-size: 18px; font-size: 18px;
color: $menuText; color: #5a5e66;
vertical-align: text-bottom; vertical-align: text-bottom;
&.hover-effect { &.hover-effect {
cursor: pointer; cursor: pointer;
transition: all 0.3s ease; transition: background .3s;
&:hover { &:hover {
background: $navbarHoverBg; background: rgba(0, 0, 0, .025)
color: $navbarRightMenuHoverColor;
filter: drop-shadow(0 0 8px $navbarRightMenuHoverGlow);
} }
} }
} }
@@ -186,13 +178,6 @@ export default {
width: 40px; width: 40px;
height: 40px; height: 40px;
border-radius: 10px; border-radius: 10px;
border: 2px solid $navbarAvatarBorderColor;
transition: all 0.3s ease;
&:hover {
border-color: $navbarAvatarHoverBorderColor;
box-shadow: 0 0 15px $navbarAvatarHoverGlow;
}
} }
.el-icon-caret-bottom { .el-icon-caret-bottom {
@@ -201,12 +186,6 @@ export default {
right: -20px; right: -20px;
top: 25px; top: 25px;
font-size: 12px; font-size: 12px;
color: $navbarCaretColor;
transition: all 0.3s ease;
&:hover {
color: $menuActiveText;
}
} }
} }
} }
@@ -26,7 +26,7 @@ export default {
href: { href: {
type: String, type: String,
required: true, required: true,
default: 'https://gitee.com/odboy-tianjun' default: 'https://github.com/odboy-tianjun'
} }
} }
} }
+1 -1
View File
@@ -220,7 +220,7 @@ export default {
.login-form-box { .login-form-box {
width: 360px; width: 360px;
height: 390px; height: 370px;
background-color: #FFFFFF; background-color: #FFFFFF;
} }
@@ -68,7 +68,7 @@
</el-dialog> </el-dialog>
<el-row :gutter="15"> <el-row :gutter="15">
<!--角色管理--> <!--角色管理-->
<el-col span="18" style="margin-bottom: 10px"> <el-col :xs="24" :sm="24" :md="16" :lg="16" :xl="17" style="margin-bottom: 10px">
<el-card class="box-card" shadow="never"> <el-card class="box-card" shadow="never">
<div slot="header" class="clearfix"> <div slot="header" class="clearfix">
<span class="role-span">角色列表</span> <span class="role-span">角色列表</span>
@@ -113,7 +113,7 @@
</el-card> </el-card>
</el-col> </el-col>
<!-- 菜单授权 --> <!-- 菜单授权 -->
<el-col span="6"> <el-col :xs="24" :sm="24" :md="8" :lg="8" :xl="7">
<el-card class="box-card" shadow="never"> <el-card class="box-card" shadow="never">
<div slot="header" class="clearfix"> <div slot="header" class="clearfix">
<el-tooltip class="item" effect="dark" content="选择指定角色分配菜单" placement="top"> <el-tooltip class="item" effect="dark" content="选择指定角色分配菜单" placement="top">
@@ -153,7 +153,7 @@
<script> <script>
import crudRoles from '@/api/system/role' import crudRoles from '@/api/system/role'
import { searchDept, searchDeptTree } from '@/api/system/dept' import { searchDept, searchDeptTree } from '@/api/system/dept'
import { listChildMenuSetByMenuId, listRoleMenuByPid } from '@/api/system/menu' import { listChildMenuSetByMenuId, listMenuByPid } from '@/api/system/menu'
import CRUD, { crud, form, header, presenter } from '@crud/crud' import CRUD, { crud, form, header, presenter } from '@crud/crud'
import rrOperation from '@crud/RR.operation' import rrOperation from '@crud/RR.operation'
import crudOperation from '@crud/CRUD.operation' import crudOperation from '@crud/CRUD.operation'
@@ -197,7 +197,7 @@ export default {
methods: { methods: {
getMenuDatas(node, resolve) { getMenuDatas(node, resolve) {
setTimeout(() => { setTimeout(() => {
listRoleMenuByPid(node.data.id ? node.data.id : 0).then(res => { listMenuByPid(node.data.id ? node.data.id : 0).then(res => {
resolve(res) resolve(res)
}) })
}, 100) }, 100)
@@ -55,8 +55,8 @@
<svg-icon icon-class="anq" /> <svg-icon icon-class="anq" />
安全设置 安全设置
<div class="user-right"> <div class="user-right">
<el-button type="text" style="padding: 0" @click="$refs.pass.dialog = true">修改密码</el-button> <a @click="$refs.pass.dialog = true">修改密码</a>
<el-button type="text" style="padding: 0" @click="$refs.email.dialog = true">修改邮箱</el-button> <a @click="$refs.email.dialog = true">修改邮箱</a>
</div> </div>
</li> </li>
</ul> </ul>
@@ -13,11 +13,13 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package cn.odboy.framework.exception; package cn.odboy.framework.exception;
import static org.springframework.http.HttpStatus.BAD_REQUEST;
import lombok.Getter; import lombok.Getter;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import static org.springframework.http.HttpStatus.BAD_REQUEST;
/** /**
* 统一异常处理 * 统一异常处理
@@ -13,11 +13,13 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package cn.odboy.framework.exception; package cn.odboy.framework.exception;
import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR;
import lombok.Getter; import lombok.Getter;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR;
@Getter @Getter
public class ServerException extends RuntimeException { public class ServerException extends RuntimeException {
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package cn.odboy.framework.exception.handler; package cn.odboy.framework.exception.handler;
import lombok.Data; import lombok.Data;
@@ -41,3 +42,5 @@ public final class ApiError {
return apiError; return apiError;
} }
} }
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package cn.odboy.framework.exception.handler; package cn.odboy.framework.exception.handler;
import cn.hutool.core.exceptions.ExceptionUtil; import cn.hutool.core.exceptions.ExceptionUtil;
@@ -76,8 +77,8 @@ public class GlobalExceptionHandler {
log.error(ExceptionUtil.stacktraceToString(e)); log.error(ExceptionUtil.stacktraceToString(e));
ObjectError objectError = e.getBindingResult().getAllErrors().get(0); ObjectError objectError = e.getBindingResult().getAllErrors().get(0);
String message = objectError.getDefaultMessage(); String message = objectError.getDefaultMessage();
if (objectError instanceof FieldError) { if (objectError instanceof FieldError fieldError) {
message = ((FieldError) objectError).getField() + ": " + message; message = fieldError.getField() + ": " + message;
} }
return buildResponseEntity(ApiError.error(message)); return buildResponseEntity(ApiError.error(message));
} }
@@ -13,19 +13,18 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package cn.odboy.framework.properties; package cn.odboy.framework.properties;
import cn.odboy.framework.properties.model.CaptchaModel; import cn.odboy.framework.properties.model.CaptchaModel;
import cn.odboy.framework.properties.model.ContentRsaEncodeSettingModel; import cn.odboy.framework.properties.model.ContentRsaEncodeSettingModel;
import cn.odboy.framework.properties.model.JwtAuthSettingModel; import cn.odboy.framework.properties.model.JwtAuthSettingModel;
import cn.odboy.framework.properties.model.StorageOSSModel; import cn.odboy.framework.properties.model.StorageOSSModel;
import cn.odboy.framework.properties.model.SwaggerApiDocSettingModel;
import cn.odboy.framework.properties.model.ThreadPoolSettingModel; import cn.odboy.framework.properties.model.ThreadPoolSettingModel;
import cn.odboy.framework.properties.model.UserLoginSettingModel; import cn.odboy.framework.properties.model.UserLoginSettingModel;
import lombok.Data; import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.util.List;
/** /**
* 应用配置 * 应用配置
@@ -41,12 +40,9 @@ public class AppProperties {
private ContentRsaEncodeSettingModel rsa; private ContentRsaEncodeSettingModel rsa;
private JwtAuthSettingModel jwt; private JwtAuthSettingModel jwt;
private UserLoginSettingModel login; private UserLoginSettingModel login;
private SwaggerApiDocSettingModel swagger;
private ThreadPoolSettingModel asyncTaskPool; private ThreadPoolSettingModel asyncTaskPool;
private CaptchaModel captcha; private CaptchaModel captcha;
private StorageOSSModel oss; private StorageOSSModel oss;
/**
* 自动识别json对象白名单配置(仅允许解析的包名, 范围越小越安全)<br/> 未配置可能导致, 登录失败, 反复登录等问题
*/
private List<String> serialWhiteList;
} }
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package cn.odboy.framework.properties.model; package cn.odboy.framework.properties.model;
import cn.odboy.base.KitObject; import cn.odboy.base.KitObject;
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package cn.odboy.framework.properties.model; package cn.odboy.framework.properties.model;
import cn.odboy.base.KitObject; import cn.odboy.base.KitObject;
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package cn.odboy.framework.properties.model; package cn.odboy.framework.properties.model;
import cn.odboy.base.KitObject; import cn.odboy.base.KitObject;
@@ -30,14 +31,17 @@ public class JwtAuthSettingModel extends KitObject {
* 必须使用最少88位的Base64对该令牌进行编码 * 必须使用最少88位的Base64对该令牌进行编码
*/ */
private String base64Secret; private String base64Secret;
/** /**
* 令牌过期时间 此处单位/毫秒 * 令牌过期时间 此处单位/毫秒
*/ */
private Long tokenValidityInSeconds; private Long tokenValidityInSeconds;
/** /**
* token 续期检查 * token 续期检查
*/ */
private Long detect; private Long detect;
/** /**
* 续期时间 * 续期时间
*/ */
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package cn.odboy.framework.properties.model; package cn.odboy.framework.properties.model;
import cn.odboy.base.KitObject; import cn.odboy.base.KitObject;
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package cn.odboy.framework.properties.model; package cn.odboy.framework.properties.model;
import lombok.Getter; import lombok.Getter;
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package cn.odboy.framework.properties.model; package cn.odboy.framework.properties.model;
import cn.odboy.base.KitObject; import cn.odboy.base.KitObject;
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package cn.odboy.framework.properties.model; package cn.odboy.framework.properties.model;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
@@ -25,9 +26,9 @@ import com.wf.captcha.ChineseGifCaptcha;
import com.wf.captcha.GifCaptcha; import com.wf.captcha.GifCaptcha;
import com.wf.captcha.SpecCaptcha; import com.wf.captcha.SpecCaptcha;
import com.wf.captcha.base.Captcha; import com.wf.captcha.base.Captcha;
import java.awt.Font;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import java.awt.*;
/** /**
* 验证码配置 * 验证码配置
@@ -39,26 +40,32 @@ import java.awt.*;
public class UserLoginCaptchaSettingModel extends KitObject { public class UserLoginCaptchaSettingModel extends KitObject {
private CaptchaCodeEnum codeType; private CaptchaCodeEnum codeType;
/** /**
* 验证码有效期 分钟 * 验证码有效期 分钟
*/ */
private Long expiration = 5L; private Long expiration = 5L;
/** /**
* 验证码内容长度 * 验证码内容长度
*/ */
private int length = 4; private int length = 4;
/** /**
* 验证码宽度 * 验证码宽度
*/ */
private int width = 111; private int width = 111;
/** /**
* 验证码高度 * 验证码高度
*/ */
private int height = 36; private int height = 36;
/** /**
* 验证码字体 * 验证码字体
*/ */
private String fontName; private String fontName;
/** /**
* 字体大小 * 字体大小
*/ */
@@ -72,30 +79,29 @@ public class UserLoginCaptchaSettingModel extends KitObject {
public Captcha getCaptcha() { public Captcha getCaptcha() {
Captcha captcha; Captcha captcha;
switch (codeType) { switch (codeType) {
case ARITHMETIC: case ARITHMETIC -> {
// 算术类型 https://gitee.com/whvse/EasyCaptcha // 算术类型 https://gitee.com/whvse/EasyCaptcha
captcha = new FixedArithmeticCaptcha(width, height); captcha = new FixedArithmeticCaptcha(width, height);
// 几位数运算, 默认是两位 // 几位数运算, 默认是两位
captcha.setLen(length); captcha.setLen(length);
break; }
case CHINESE: case CHINESE -> {
captcha = new ChineseCaptcha(width, height); captcha = new ChineseCaptcha(width, height);
captcha.setLen(length); captcha.setLen(length);
break; }
case CHINESE_GIF: case CHINESE_GIF -> {
captcha = new ChineseGifCaptcha(width, height); captcha = new ChineseGifCaptcha(width, height);
captcha.setLen(length); captcha.setLen(length);
break; }
case GIF: case GIF -> {
captcha = new GifCaptcha(width, height); captcha = new GifCaptcha(width, height);
captcha.setLen(length); captcha.setLen(length);
break; }
case SPEC: case SPEC -> {
captcha = new SpecCaptcha(width, height); captcha = new SpecCaptcha(width, height);
captcha.setLen(length); captcha.setLen(length);
break; }
default: default -> throw new BadRequestException("验证码配置信息错误!正确配置查看 LoginCodeEnum ");
throw new BadRequestException("验证码配置信息错误!正确配置查看 LoginCodeEnum ");
} }
if (StrUtil.isNotBlank(fontName)) { if (StrUtil.isNotBlank(fontName)) {
captcha.setFont(new Font(fontName, Font.PLAIN, fontSize)); captcha.setFont(new Font(fontName, Font.PLAIN, fontSize));
@@ -114,12 +120,15 @@ public class UserLoginCaptchaSettingModel extends KitObject {
// 生成随机数字和运算符 // 生成随机数字和运算符
int n1 = num(1, 10), n2 = num(1, 10); int n1 = num(1, 10), n2 = num(1, 10);
int opt = num(3); int opt = num(3);
// 计算结果 // 计算结果
int res = new int[]{n1 + n2, n1 - n2, n1 * n2}[opt]; int res = new int[]{n1 + n2, n1 - n2, n1 * n2}[opt];
// 转换为字符运算符 // 转换为字符运算符
char optChar = "+-x".charAt(opt); char optChar = "+-x".charAt(opt);
this.setArithmeticString(String.format("%s%c%s=?", n1, optChar, n2)); this.setArithmeticString(String.format("%s%c%s=?", n1, optChar, n2));
this.chars = String.valueOf(res); this.chars = String.valueOf(res);
return chars.toCharArray(); return chars.toCharArray();
} }
} }
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package cn.odboy.framework.properties.model; package cn.odboy.framework.properties.model;
import cn.odboy.base.KitObject; import cn.odboy.base.KitObject;
@@ -20,6 +20,15 @@ import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSON;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.data.redis.connection.RedisConnection; import org.springframework.data.redis.connection.RedisConnection;
@@ -31,15 +40,6 @@ import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ScanOptions; import org.springframework.data.redis.core.ScanOptions;
import org.springframework.data.redis.serializer.StringRedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@Component @Component
public class KitRedisHelper { public class KitRedisHelper {
@@ -280,8 +280,7 @@ public class KitRedisHelper {
if (value == null) { if (value == null) {
return null; return null;
} }
if (value instanceof List<?>) { if (value instanceof List<?> list) {
List<?> list = (List<?>) value;
// 检查每个元素是否为指定类型 // 检查每个元素是否为指定类型
if (list.stream().allMatch(clazz::isInstance)) { if (list.stream().allMatch(clazz::isInstance)) {
return list.stream().map(clazz::cast).collect(Collectors.toList()); return list.stream().map(clazz::cast).collect(Collectors.toList());
@@ -13,20 +13,22 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package cn.odboy.framework.redis; package cn.odboy.framework.redis;
import cn.odboy.framework.properties.AppProperties;
import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONFactory; import com.alibaba.fastjson2.JSONFactory;
import com.alibaba.fastjson2.JSONWriter; import com.alibaba.fastjson2.JSONWriter;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
import lombok.NonNull; import lombok.NonNull;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.MurmurHash3; import org.apache.commons.codec.digest.MurmurHash3;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration; import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.cache.Cache; import org.springframework.cache.Cache;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching; import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.CacheErrorHandler; import org.springframework.cache.interceptor.CacheErrorHandler;
import org.springframework.cache.interceptor.KeyGenerator; import org.springframework.cache.interceptor.KeyGenerator;
@@ -41,19 +43,19 @@ import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer; import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.SerializationException; import org.springframework.data.redis.serializer.SerializationException;
import org.springframework.data.redis.serializer.StringRedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
@Slf4j @Slf4j
@Configuration @Configuration
@EnableCaching @EnableCaching
@AutoConfigureBefore(RedisAutoConfiguration.class) @AutoConfigureBefore(RedisAutoConfiguration.class)
public class RedisConfiguration extends CachingConfigurerSupport { public class RedisConfiguration {
@Autowired /**
private AppProperties properties; * 自动识别json对象白名单配置(仅允许解析的包名, 范围越小越安全)<br/> 未配置可能导致, 登录失败, 反复登录等问题
*/
private static final String[] WHITELIST_STR =
{"org.springframework", "cn.odboy.system.dal.dataobject", "cn.odboy.system.dal.model",
"cn.odboy.task.dal.dataobject", "cn.odboy.task.dal.model",};
/** /**
* 设置 redis 数据默认过期时间,默认2小时 设置@cacheable 序列化方式 * 设置 redis 数据默认过期时间,默认2小时 设置@cacheable 序列化方式
@@ -62,7 +64,8 @@ public class RedisConfiguration extends CachingConfigurerSupport {
public RedisCacheConfiguration redisCacheConfiguration() { public RedisCacheConfiguration redisCacheConfiguration() {
FastJsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class); FastJsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class);
RedisCacheConfiguration configuration = RedisCacheConfiguration.defaultCacheConfig(); RedisCacheConfiguration configuration = RedisCacheConfiguration.defaultCacheConfig();
configuration = configuration.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(fastJsonRedisSerializer)) configuration = configuration.serializeValuesWith(
RedisSerializationContext.SerializationPair.fromSerializer(fastJsonRedisSerializer))
.entryTtl(Duration.ofHours(2)); .entryTtl(Duration.ofHours(2));
return configuration; return configuration;
} }
@@ -76,9 +79,8 @@ public class RedisConfiguration extends CachingConfigurerSupport {
template.setValueSerializer(fastJsonRedisSerializer); template.setValueSerializer(fastJsonRedisSerializer);
template.setHashValueSerializer(fastJsonRedisSerializer); template.setHashValueSerializer(fastJsonRedisSerializer);
// 设置fastJson的序列化白名单 // 设置fastJson的序列化白名单
for (String pack : properties.getSerialWhiteList()) { for (String pack : WHITELIST_STR) {
JSONFactory.getDefaultObjectReaderProvider().addAutoTypeAccept(pack); JSONFactory.getDefaultObjectReaderProvider().addAutoTypeAccept(pack);
log.warn("设置fastJson的序列化白名单:{}", pack);
} }
// key的序列化采用StringRedisSerializer // key的序列化采用StringRedisSerializer
template.setKeySerializer(new StringRedisSerializer()); template.setKeySerializer(new StringRedisSerializer());
@@ -102,8 +104,8 @@ public class RedisConfiguration extends CachingConfigurerSupport {
/** /**
* 自定义缓存key生成策略 * 自定义缓存key生成策略
*/ */
@Bean @Bean
@Override
public KeyGenerator keyGenerator() { public KeyGenerator keyGenerator() {
return (target, method, params) -> { return (target, method, params) -> {
Map<String, Object> container = new HashMap<>(8); Map<String, Object> container = new HashMap<>(8);
@@ -135,7 +137,7 @@ public class RedisConfiguration extends CachingConfigurerSupport {
} }
@Override @Override
public void handleCachePutError(@NonNull RuntimeException exception, @NonNull Cache cache, @NonNull Object key, Object value) { public void handleCachePutError(@NonNull RuntimeException exception, @NonNull Cache cache, @NonNull Object key, @NonNull Object value) {
// 处理缓存写入错误 // 处理缓存写入错误
log.error("Cache Put Error: {}", exception.getMessage()); log.error("Cache Put Error: {}", exception.getMessage());
} }
@@ -17,14 +17,6 @@ package cn.odboy.util;
import cn.odboy.annotation.AnonymousAccess; import cn.odboy.annotation.AnonymousAccess;
import cn.odboy.constant.RequestMethodEnum; import cn.odboy.constant.RequestMethodEnum;
import lombok.experimental.UtilityClass;
import org.springframework.context.ApplicationContext;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.condition.PathPatternsRequestCondition;
import org.springframework.web.servlet.mvc.condition.PatternsRequestCondition;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
@@ -32,6 +24,13 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.Set; import java.util.Set;
import lombok.experimental.UtilityClass;
import org.springframework.context.ApplicationContext;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.condition.PatternsRequestCondition;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
/** /**
* 匿名标记工具 * 匿名标记工具
@@ -46,9 +45,10 @@ public class KitAnonTagUtil {
* @return / * @return /
*/ */
public static Map<String, Set<String>> getAnonymousUrl(final ApplicationContext applicationContext) { public static Map<String, Set<String>> getAnonymousUrl(final ApplicationContext applicationContext) {
RequestMappingHandlerMapping requestMappingHandlerMapping = (RequestMappingHandlerMapping) applicationContext.getBean("requestMappingHandlerMapping"); RequestMappingHandlerMapping requestMappingHandlerMapping =
(RequestMappingHandlerMapping) applicationContext.getBean("requestMappingHandlerMapping");
Map<RequestMappingInfo, HandlerMethod> handlerMethodMap = requestMappingHandlerMapping.getHandlerMethods(); Map<RequestMappingInfo, HandlerMethod> handlerMethodMap = requestMappingHandlerMapping.getHandlerMethods();
Map<String, Set<String>> anonymousUrls = new HashMap<>(8); Map<String, java.util.Set<String>> anonymousUrls = new HashMap<>(8);
// 获取匿名标记 // 获取匿名标记
Set<String> get = new HashSet<>(); Set<String> get = new HashSet<>();
Set<String> post = new HashSet<>(); Set<String> post = new HashSet<>();
@@ -60,28 +60,30 @@ public class KitAnonTagUtil {
HandlerMethod handlerMethod = infoEntry.getValue(); HandlerMethod handlerMethod = infoEntry.getValue();
AnonymousAccess anonymousAccess = handlerMethod.getMethodAnnotation(AnonymousAccess.class); AnonymousAccess anonymousAccess = handlerMethod.getMethodAnnotation(AnonymousAccess.class);
if (null != anonymousAccess && infoEntry.getKey() != null) { if (null != anonymousAccess && infoEntry.getKey() != null) {
List<RequestMethod> requestMethods = new ArrayList<>(infoEntry.getKey().getMethodsCondition().getMethods()); List<RequestMethod> requestMethods =
RequestMethodEnum request = RequestMethodEnum.find(requestMethods.isEmpty() ? RequestMethodEnum.ALL.getType() : requestMethods.get(0).name()); new ArrayList<>(infoEntry.getKey().getMethodsCondition().getMethods());
PathPatternsRequestCondition patternsCondition = infoEntry.getKey().getPathPatternsCondition(); RequestMethodEnum request = RequestMethodEnum.find(
requestMethods.isEmpty() ? RequestMethodEnum.ALL.getType() : requestMethods.get(0).name());
PatternsRequestCondition patternsCondition = infoEntry.getKey().getPatternsCondition();
if (patternsCondition != null) { if (patternsCondition != null) {
switch (Objects.requireNonNull(request)) { switch (Objects.requireNonNull(request)) {
case GET: case GET:
get.addAll(patternsCondition.getPatternValues()); get.addAll(patternsCondition.getPatterns());
break; break;
case POST: case POST:
post.addAll(patternsCondition.getPatternValues()); post.addAll(patternsCondition.getPatterns());
break; break;
case PUT: case PUT:
put.addAll(patternsCondition.getPatternValues()); put.addAll(patternsCondition.getPatterns());
break; break;
case PATCH: case PATCH:
patch.addAll(patternsCondition.getPatternValues()); patch.addAll(patternsCondition.getPatterns());
break; break;
case DELETE: case DELETE:
delete.addAll(patternsCondition.getPatternValues()); delete.addAll(patternsCondition.getPatterns());
break; break;
default: default:
all.addAll(patternsCondition.getPatternValues()); all.addAll(patternsCondition.getPatterns());
break; break;
} }
} }
@@ -17,8 +17,8 @@ package cn.odboy.util;
import cn.hutool.core.codec.Base64Encoder; import cn.hutool.core.codec.Base64Encoder;
import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.IdUtil;
import lombok.experimental.UtilityClass;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import lombok.experimental.UtilityClass;
/** /**
* 加密令牌生成工具 * 加密令牌生成工具
@@ -17,10 +17,10 @@ package cn.odboy.util;
import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions; import cn.hutool.core.bean.copier.CopyOptions;
import lombok.experimental.UtilityClass;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import lombok.experimental.UtilityClass;
/** /**
* Bean拷贝相关 * Bean拷贝相关
@@ -15,10 +15,9 @@
*/ */
package cn.odboy.util; package cn.odboy.util;
import lombok.experimental.UtilityClass;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.RoundingMode; import java.math.RoundingMode;
import java.text.NumberFormat; import lombok.experimental.UtilityClass;
/** /**
* 计算类 * 计算类
@@ -134,23 +133,6 @@ public final class KitBigDecimalUtil {
return yuan.multiply(BigDecimal.valueOf(100)).setScale(0, RoundingMode.HALF_UP).longValue(); return yuan.multiply(BigDecimal.valueOf(100)).setScale(0, RoundingMode.HALF_UP).longValue();
} }
/**
* 格式化为 xxx,xxx,xxx 格式
*
* @param obj 金额
* @return /
*/
public static String formatGroupingAmount(Object obj) {
if (obj == null) {
return "0";
}
BigDecimal bigDecimal = toBigDecimal(obj);
NumberFormat nf = NumberFormat.getInstance();
// 启用千位分隔符
nf.setGroupingUsed(true);
return nf.format(bigDecimal.setScale(0, RoundingMode.HALF_UP));
}
public static void main(String[] args) { public static void main(String[] args) {
BigDecimal num1 = new BigDecimal("10.123"); BigDecimal num1 = new BigDecimal("10.123");
BigDecimal num2 = new BigDecimal("2.456"); BigDecimal num2 = new BigDecimal("2.456");
@@ -17,11 +17,11 @@ package cn.odboy.util;
import cn.hutool.http.useragent.UserAgent; import cn.hutool.http.useragent.UserAgent;
import cn.hutool.http.useragent.UserAgentUtil; import cn.hutool.http.useragent.UserAgentUtil;
import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;
import jakarta.servlet.http.HttpServletRequest;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.UnknownHostException; import java.net.UnknownHostException;
import jakarta.servlet.http.HttpServletRequest;
import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;
/** /**
* 浏览器 相关 * 浏览器 相关
@@ -15,10 +15,10 @@
*/ */
package cn.odboy.util; package cn.odboy.util;
import lombok.experimental.UtilityClass;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import lombok.experimental.UtilityClass;
/** /**
* 类 相关 * 类 相关
@@ -15,8 +15,8 @@
*/ */
package cn.odboy.util; package cn.odboy.util;
import lombok.experimental.UtilityClass;
import java.io.Closeable; import java.io.Closeable;
import lombok.experimental.UtilityClass;
/** /**
* 用于关闭各种连接, 缺啥补啥 * 用于关闭各种连接, 缺啥补啥
@@ -15,9 +15,10 @@
*/ */
package cn.odboy.util; package cn.odboy.util;
import cn.hutool.core.collection.CollUtil;
import cn.odboy.base.KitSelectOptionVo; import cn.odboy.base.KitSelectOptionVo;
import cn.odboy.framework.exception.BadRequestException;
import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSON;
import lombok.experimental.UtilityClass;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.RoundingMode; import java.math.RoundingMode;
@@ -30,6 +31,7 @@ import java.util.Objects;
import java.util.function.Function; import java.util.function.Function;
import java.util.function.Predicate; import java.util.function.Predicate;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import lombok.experimental.UtilityClass;
/** /**
* 集合工具 * 集合工具
@@ -192,7 +194,7 @@ public final class KitCollUtil extends cn.hutool.core.collection.CollUtil {
* @return / * @return /
*/ */
public static BigDecimal streamBigDecimalAvg(List<BigDecimal> data) { public static BigDecimal streamBigDecimalAvg(List<BigDecimal> data) {
KitValidUtil.isEmpty(data, "data"); KitValidUtil.notEmpty(data, "data");
return data.stream().filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add) return data.stream().filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add)
.divide(BigDecimal.valueOf(data.size()), 6, RoundingMode.FLOOR); .divide(BigDecimal.valueOf(data.size()), 6, RoundingMode.FLOOR);
} }
@@ -17,9 +17,8 @@ package cn.odboy.util;
import cn.hutool.core.date.DatePattern; import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil; import cn.hutool.core.date.DateUtil;
import lombok.experimental.UtilityClass;
import java.util.Calendar;
import java.util.Date; import java.util.Date;
import lombok.experimental.UtilityClass;
/** /**
* 时间相关工具 * 时间相关工具
@@ -130,22 +129,4 @@ public class KitDateUtil {
} }
return result.toString(); return result.toString();
} }
/**
* 获得当天是周几
*/
public static String getWeekDay() {
String[] weekDays = {"星期天", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"};
Calendar cal = Calendar.getInstance();
cal.setTime(new Date());
int w = cal.get(Calendar.DAY_OF_WEEK) - 1;
if (w < 0) {
w = 0;
}
return weekDays[w];
}
public static void main(String[] args) {
System.err.println(getWeekDay());
}
} }
@@ -15,13 +15,13 @@
*/ */
package cn.odboy.util; package cn.odboy.util;
import lombok.experimental.UtilityClass; import java.nio.charset.StandardCharsets;
import javax.crypto.Cipher; import javax.crypto.Cipher;
import javax.crypto.SecretKey; import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory; import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec; import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.IvParameterSpec;
import java.nio.charset.StandardCharsets; import lombok.experimental.UtilityClass;
/** /**
* DES加密 * DES加密
@@ -15,6 +15,11 @@
*/ */
package cn.odboy.util; package cn.odboy.util;
import static cn.odboy.constant.SystemConst.SYMBOL_ADD;
import static cn.odboy.constant.SystemConst.SYMBOL_AT;
import static cn.odboy.constant.SystemConst.SYMBOL_EQUAL;
import static cn.odboy.constant.SystemConst.SYMBOL_SUBTRACT;
import cn.hutool.core.io.FileUtil; import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil; import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.IdUtil;
@@ -24,11 +29,6 @@ import cn.hutool.poi.excel.ExcelUtil;
import cn.odboy.constant.FileTypeEnum; import cn.odboy.constant.FileTypeEnum;
import cn.odboy.constant.SystemConst; import cn.odboy.constant.SystemConst;
import cn.odboy.framework.exception.BadRequestException; import cn.odboy.framework.exception.BadRequestException;
import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.util.IOUtils;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.springframework.web.multipart.MultipartFile;
import jakarta.servlet.ServletOutputStream; import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
@@ -46,10 +46,11 @@ import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static cn.odboy.constant.SystemConst.SYMBOL_ADD; import lombok.experimental.UtilityClass;
import static cn.odboy.constant.SystemConst.SYMBOL_AT; import lombok.extern.slf4j.Slf4j;
import static cn.odboy.constant.SystemConst.SYMBOL_EQUAL; import org.apache.poi.util.IOUtils;
import static cn.odboy.constant.SystemConst.SYMBOL_SUBTRACT; import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.springframework.web.multipart.MultipartFile;
/** /**
* File工具类, 扩展 hutool 工具包 * File工具类, 扩展 hutool 工具包
@@ -16,12 +16,12 @@
package cn.odboy.util; package cn.odboy.util;
import cn.odboy.framework.context.KitSpringBeanHolder; import cn.odboy.framework.context.KitSpringBeanHolder;
import lombok.experimental.UtilityClass;
import net.dreamlu.mica.ip2region.core.Ip2regionSearcher;
import net.dreamlu.mica.ip2region.core.IpInfo;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.NetworkInterface; import java.net.NetworkInterface;
import java.util.Enumeration; import java.util.Enumeration;
import lombok.experimental.UtilityClass;
import net.dreamlu.mica.ip2region.core.Ip2regionSearcher;
import net.dreamlu.mica.ip2region.core.IpInfo;
/** /**
* IP地址 相关 * IP地址 相关
@@ -17,9 +17,9 @@ package cn.odboy.util;
import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.TypeReference; import com.alibaba.fastjson2.TypeReference;
import lombok.experimental.UtilityClass;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import lombok.experimental.UtilityClass;
/** /**
* Json工具 * Json工具
@@ -17,11 +17,11 @@ package cn.odboy.util;
import cn.hutool.core.date.DateTime; import cn.hutool.core.date.DateTime;
import cn.odboy.base.KitBaseUserTimeTb; import cn.odboy.base.KitBaseUserTimeTb;
import lombok.experimental.UtilityClass;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import lombok.experimental.UtilityClass;
/** /**
* List 工具 * List 工具
@@ -40,7 +40,7 @@ public final class KitListUtil {
*/ */
public static <T, K> List<T> distinctByArgs(List<T> items, Function<? super T, ? extends K> classifier) { public static <T, K> List<T> distinctByArgs(List<T> items, Function<? super T, ? extends K> classifier) {
return items.stream().collect(Collectors.groupingBy(classifier)).values().stream() return items.stream().collect(Collectors.groupingBy(classifier)).values().stream()
.map(monitorItem -> monitorItem.iterator().next()).collect(Collectors.toList()); .map(List::getFirst).collect(Collectors.toList());
} }
/** /**
@@ -17,9 +17,9 @@ package cn.odboy.util;
import cn.odboy.base.KitPageResult; import cn.odboy.base.KitPageResult;
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage;
import lombok.experimental.UtilityClass;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import lombok.experimental.UtilityClass;
/** /**
* 分页工具 * 分页工具
@@ -15,13 +15,13 @@
*/ */
package cn.odboy.util; package cn.odboy.util;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
/** /**
* 返回值处理 工具 * 返回值处理 工具
@@ -15,9 +15,6 @@
*/ */
package cn.odboy.util; package cn.odboy.util;
import lombok.experimental.UtilityClass;
import org.apache.commons.codec.binary.Base64;
import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.security.KeyFactory; import java.security.KeyFactory;
import java.security.KeyPair; import java.security.KeyPair;
@@ -29,6 +26,9 @@ import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey; import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec; import java.security.spec.X509EncodedKeySpec;
import javax.crypto.Cipher;
import lombok.experimental.UtilityClass;
import org.apache.commons.codec.binary.Base64;
/** /**
* Rsa 工具类, 公钥私钥生成, 加解密 * Rsa 工具类, 公钥私钥生成, 加解密
@@ -15,6 +15,8 @@
*/ */
package cn.odboy.util; package cn.odboy.util;
import java.util.Calendar;
import java.util.Date;
import lombok.experimental.UtilityClass; import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@@ -95,4 +97,19 @@ public final class KitStringUtil {
} }
return sb.toString(); return sb.toString();
} }
/**
* 获得当天是周几
*/
public static String getWeekDay() {
// String[] weekDays = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
String[] weekDays = {"星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期天"};
Calendar cal = Calendar.getInstance();
cal.setTime(new Date());
int w = cal.get(Calendar.DAY_OF_WEEK) - 1;
if (w < 0) {
w = 0;
}
return weekDays[w];
}
} }
@@ -1,17 +0,0 @@
package cn.odboy.util;
import cn.hutool.core.thread.ThreadUtil;
public class KitThreadUtil {
/**
* 可中断的睡眠
*/
public static void interruptSleep(int i) throws InterruptedException {
Thread.sleep(i);
}
public static void safeSleep(int i) {
ThreadUtil.safeSleep(i);
}
}
@@ -18,16 +18,16 @@ package cn.odboy.util;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import cn.odboy.framework.exception.BadRequestException; import cn.odboy.framework.exception.BadRequestException;
import lombok.experimental.UtilityClass; import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import jakarta.validation.ConstraintViolation; import jakarta.validation.ConstraintViolation;
import jakarta.validation.Validation; import jakarta.validation.Validation;
import jakarta.validation.Validator; import jakarta.validation.Validator;
import jakarta.validation.ValidatorFactory; import jakarta.validation.ValidatorFactory;
import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
import jakarta.validation.groups.Default; import jakarta.validation.groups.Default;
import java.util.List; import lombok.experimental.UtilityClass;
import java.util.Set;
import java.util.stream.Collectors;
/** /**
* Bean验证工具 * Bean验证工具
@@ -46,12 +46,6 @@ public final class KitValidUtil {
} }
} }
/**
* 验证实体是否通过校验 <br/> 实体内通过 javax.validation.constraints 中的表达式限制参数 <br/>
*
* @param object /
* @param <T> /
*/
public static <T> void validate(T object) { public static <T> void validate(T object) {
Set<ConstraintViolation<T>> violations = VALIDATOR.validate(object, Default.class); Set<ConstraintViolation<T>> violations = VALIDATOR.validate(object, Default.class);
if (!violations.isEmpty()) { if (!violations.isEmpty()) {
@@ -60,125 +54,39 @@ public final class KitValidUtil {
} }
} }
/** public static void notNull(Object value) {
* 参数为null,抛异常
*
* @param value 参数值
*/
public static void isNull(Object value) {
if (value == null) { if (value == null) {
throw new BadRequestException("参数必填"); throw new BadRequestException("参数必填");
} }
} }
/** public static void isNull(Object value) {
* 参数为空,抛异常 if (value != null) {
* throw new BadRequestException("参数非必填");
* @param value 参数值 }
* @param name 参数名称 }
* @param code 参数编码
*/ public static void notNull(Object value, @NotNull String name, @NotNull String code) {
public static void isNull(Object value, @NotNull String name, @NotNull String code) {
if (value == null) { if (value == null) {
throw new BadRequestException(String.format("参数 %s(%s) 必填", name, code)); throw new BadRequestException(String.format("参数 %s(%s) 必填", name, code));
} }
} }
/**
* 参数为空,抛异常
*
* @param value 参数值
* @param message 异常信息
*/
public static void isNull(Object value, @NotNull String message) {
if (value == null) {
throw new BadRequestException(message);
}
}
/**
* 参数为空,抛异常
*
* @param value 参数值
* @param code 参数编码
*/
public static void isNullF(Object value, @NotNull String code) {
if (value == null) {
throw new BadRequestException(String.format("参数 %s 必填", code));
}
}
/**
* 参数为空字符串,抛异常
*
* @param value 参数值
* @param name 参数名称
* @param code 参数编码
*/
public static void isBlank(CharSequence value, @NotNull String name, @NotNull String code) { public static void isBlank(CharSequence value, @NotNull String name, @NotNull String code) {
if (StrUtil.isNotBlank(value)) {
throw new BadRequestException(String.format("参数 %s(%s) 非必填", name, code));
}
}
public static void notBlank(CharSequence value, @NotNull String name, @NotNull String code) {
if (StrUtil.isBlank(value)) { if (StrUtil.isBlank(value)) {
throw new BadRequestException(String.format("参数 %s(%s) 必填", name, code)); throw new BadRequestException(String.format("参数 %s(%s) 必填", name, code));
} }
} }
/** public static void notEmpty(List<?> data, @NotNull String code) {
* 集合为空,抛异常
*
* @param data 集合值
* @param code 参数编码
*/
public static void isEmpty(List<?> data, @NotNull String code) {
if (CollUtil.isEmpty(data)) { if (CollUtil.isEmpty(data)) {
throw new BadRequestException(String.format("参数 %s 必填", code)); throw new BadRequestException(String.format("参数 %s 必填", code));
} }
} }
/**
* 集合为空,抛异常
*
* @param data 集合值
* @param name 参数名称
* @param code 参数编码
*/
public static void isEmpty(List<?> data, @NotNull String name, @NotNull String code) {
if (CollUtil.isEmpty(data)) {
throw new BadRequestException(String.format("参数 %s(%s) 必填", name, code));
}
}
/**
* 表达式为true,抛异常
*
* @param condition 表达式
* @param message 异常信息
*/
public static void isTrue(boolean condition, String message) {
if (condition) {
throw new BadRequestException(message);
}
}
/**
* 表达式为false,抛异常
*
* @param condition 表达式
* @param message 异常信息
*/
public static void isFalse(boolean condition, String message) {
if (!condition) {
throw new BadRequestException(message);
}
}
/**
* 参数为空字符串,抛异常
*
* @param value 参数值
* @param message 异常信息
*/
public static void isBlank(String value, String message) {
if (StrUtil.isBlank(value)) {
throw new BadRequestException(message);
}
}
} }
@@ -3,12 +3,12 @@ package cn.odboy.util.xlsx;
import cn.hutool.core.date.DatePattern; import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil; import cn.hutool.core.date.DateUtil;
import cn.idev.excel.EasyExcel; import cn.idev.excel.EasyExcel;
import jakarta.servlet.http.HttpServletResponse;
import java.io.OutputStream; import java.io.OutputStream;
import java.net.URLEncoder; import java.net.URLEncoder;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import jakarta.servlet.http.HttpServletResponse;
/** /**
* EasyExcel 导出增强工具类 (支持普通/分页模式) * EasyExcel 导出增强工具类 (支持普通/分页模式)
@@ -6,14 +6,14 @@ import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import cn.idev.excel.FastExcel; import cn.idev.excel.FastExcel;
import cn.odboy.framework.exception.BadRequestException; import cn.odboy.framework.exception.BadRequestException;
import lombok.experimental.UtilityClass;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.IOException;
import java.net.URLEncoder; import java.net.URLEncoder;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import jakarta.servlet.http.HttpServletResponse;
import lombok.experimental.UtilityClass;
/** /**
* xlsx文件导出工具 * xlsx文件导出工具
@@ -1,18 +1,3 @@
/*
* Copyright 2021-2026 Odboy
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.odboy.system.application; package cn.odboy.system.application;
import cn.odboy.system.application.model.CuteDeptTreeVo; import cn.odboy.system.application.model.CuteDeptTreeVo;
@@ -1,18 +1,3 @@
/*
* Copyright 2021-2026 Odboy
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.odboy.system.application; package cn.odboy.system.application;
import cn.odboy.system.application.service.CuteFileUploadService; import cn.odboy.system.application.service.CuteFileUploadService;
@@ -1,18 +1,3 @@
/*
* Copyright 2021-2026 Odboy
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.odboy.system.application; package cn.odboy.system.application;
import cn.odboy.system.application.service.CuteProductLineSelectService; import cn.odboy.system.application.service.CuteProductLineSelectService;
@@ -1,18 +1,3 @@
/*
* Copyright 2021-2026 Odboy
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.odboy.system.application; package cn.odboy.system.application;
import cn.odboy.system.application.service.CuteProductLineSelectProService; import cn.odboy.system.application.service.CuteProductLineSelectProService;
@@ -1,18 +1,3 @@
/*
* Copyright 2021-2026 Odboy
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.odboy.system.application; package cn.odboy.system.application;
import cn.odboy.system.application.model.CuteUserSelectVo; import cn.odboy.system.application.model.CuteUserSelectVo;
@@ -1,18 +1,3 @@
/*
* Copyright 2021-2026 Odboy
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.odboy.system.application.model; package cn.odboy.system.application.model;
import cn.odboy.base.KitObject; import cn.odboy.base.KitObject;
@@ -1,18 +1,3 @@
/*
* Copyright 2021-2026 Odboy
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.odboy.system.application.model; package cn.odboy.system.application.model;
import cn.odboy.base.KitObject; import cn.odboy.base.KitObject;
@@ -1,18 +1,3 @@
/*
* Copyright 2021-2026 Odboy
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.odboy.system.application.service; package cn.odboy.system.application.service;
import cn.odboy.system.dal.dataobject.SystemDeptTb; import cn.odboy.system.dal.dataobject.SystemDeptTb;
@@ -1,18 +1,3 @@
/*
* Copyright 2021-2026 Odboy
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.odboy.system.application.service; package cn.odboy.system.application.service;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
@@ -1,18 +1,3 @@
/*
* Copyright 2021-2026 Odboy
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.odboy.system.application.service; package cn.odboy.system.application.service;
import cn.hutool.core.date.DatePattern; import cn.hutool.core.date.DatePattern;
@@ -1,18 +1,3 @@
/*
* Copyright 2021-2026 Odboy
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.odboy.system.application.service; package cn.odboy.system.application.service;
import cn.odboy.system.application.model.CuteProductLineSelectProVo; import cn.odboy.system.application.model.CuteProductLineSelectProVo;
@@ -1,18 +1,3 @@
/*
* Copyright 2021-2026 Odboy
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.odboy.system.application.service; package cn.odboy.system.application.service;
import cn.odboy.system.application.model.CuteProductLineSelectVo; import cn.odboy.system.application.model.CuteProductLineSelectVo;
@@ -1,18 +1,3 @@
/*
* Copyright 2021-2026 Odboy
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.odboy.system.application.service; package cn.odboy.system.application.service;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
@@ -17,6 +17,7 @@ package cn.odboy.system.controller;
import cn.odboy.base.KitPageArgs; import cn.odboy.base.KitPageArgs;
import cn.odboy.base.KitPageResult; import cn.odboy.base.KitPageResult;
import cn.odboy.framework.exception.BadRequestException;
import cn.odboy.system.dal.dataobject.SystemMenuTb; import cn.odboy.system.dal.dataobject.SystemMenuTb;
import cn.odboy.system.dal.model.request.SystemQueryMenuArgs; import cn.odboy.system.dal.model.request.SystemQueryMenuArgs;
import cn.odboy.system.dal.model.response.SystemMenuRouterVo; import cn.odboy.system.dal.model.response.SystemMenuRouterVo;
@@ -101,6 +102,9 @@ public class SystemMenuController {
@PostMapping(value = "/saveMenu") @PostMapping(value = "/saveMenu")
@PreAuthorize("@el.check('menu:add')") @PreAuthorize("@el.check('menu:add')")
public ResponseEntity<Void> saveMenu(@Validated @RequestBody SystemMenuTb args) { public ResponseEntity<Void> saveMenu(@Validated @RequestBody SystemMenuTb args) {
if (args.getId() != null) {
throw new BadRequestException("无效参数id");
}
systemMenuService.saveMenu(args); systemMenuService.saveMenu(args);
return ResponseEntity.ok(null); return ResponseEntity.ok(null);
} }
@@ -21,8 +21,10 @@ import cn.odboy.system.dal.dataobject.SystemQuartzJobTb;
import cn.odboy.system.dal.dataobject.SystemQuartzLogTb; import cn.odboy.system.dal.dataobject.SystemQuartzLogTb;
import cn.odboy.system.dal.model.request.SystemQueryQuartzJobArgs; import cn.odboy.system.dal.model.request.SystemQueryQuartzJobArgs;
import cn.odboy.system.dal.model.request.SystemUpdateQuartzJobArgs; import cn.odboy.system.dal.model.request.SystemUpdateQuartzJobArgs;
import cn.odboy.system.dal.model.response.SystemQuartzJobVo;
import cn.odboy.system.framework.operalog.OperationLog; import cn.odboy.system.framework.operalog.OperationLog;
import cn.odboy.system.service.SystemQuartzJobService; import cn.odboy.system.service.SystemQuartzJobService;
import cn.odboy.util.KitBeanUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
@@ -94,7 +96,8 @@ public class SystemQuartzJobController {
@ApiOperation("修改定时任务") @ApiOperation("修改定时任务")
@PostMapping(value = "/updateQuartzJobResumeCron") @PostMapping(value = "/updateQuartzJobResumeCron")
@PreAuthorize("@el.check('quartzJob:edit')") @PreAuthorize("@el.check('quartzJob:edit')")
public ResponseEntity<Void> updateQuartzJob(@Validated(SystemQuartzJobTb.Update.class) @RequestBody SystemUpdateQuartzJobArgs args) { public ResponseEntity<Void> updateQuartzJob(
@Validated(SystemQuartzJobTb.Update.class) @RequestBody SystemUpdateQuartzJobArgs args) {
systemQuartzJobService.updateQuartzJobResumeCron(args); systemQuartzJobService.updateQuartzJobResumeCron(args);
return ResponseEntity.ok(null); return ResponseEntity.ok(null);
} }
@@ -105,7 +108,8 @@ public class SystemQuartzJobController {
@PreAuthorize("@el.check('quartzJob:edit')") @PreAuthorize("@el.check('quartzJob:edit')")
public ResponseEntity<Void> switchQuartzJobStatus(@PathVariable Long id) { public ResponseEntity<Void> switchQuartzJobStatus(@PathVariable Long id) {
SystemQuartzJobTb quartzJobTb = systemQuartzJobService.getQuartzJobById(id); SystemQuartzJobTb quartzJobTb = systemQuartzJobService.getQuartzJobById(id);
systemQuartzJobService.switchQuartzJobStatus(quartzJobTb); SystemQuartzJobVo quartzJobVo = KitBeanUtil.copyToClass(quartzJobTb, SystemQuartzJobVo.class);
systemQuartzJobService.switchQuartzJobStatus(quartzJobVo);
return ResponseEntity.ok(null); return ResponseEntity.ok(null);
} }
@@ -115,7 +119,8 @@ public class SystemQuartzJobController {
@PreAuthorize("@el.check('quartzJob:edit')") @PreAuthorize("@el.check('quartzJob:edit')")
public ResponseEntity<Void> startQuartzJob(@PathVariable Long id) { public ResponseEntity<Void> startQuartzJob(@PathVariable Long id) {
SystemQuartzJobTb quartzJobTb = systemQuartzJobService.getQuartzJobById(id); SystemQuartzJobTb quartzJobTb = systemQuartzJobService.getQuartzJobById(id);
systemQuartzJobService.startQuartzJob(quartzJobTb); SystemQuartzJobVo quartzJobVo = KitBeanUtil.copyToClass(quartzJobTb, SystemQuartzJobVo.class);
systemQuartzJobService.startQuartzJob(quartzJobVo);
return ResponseEntity.ok(null); return ResponseEntity.ok(null);
} }
@@ -20,9 +20,9 @@ import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
import jakarta.validation.constraints.NotBlank;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
import java.util.Objects; import java.util.Objects;
@@ -63,10 +63,4 @@ public class SystemQuartzJobTb extends KitBaseUserTimeTb {
@ApiModelProperty(value = "备注") @ApiModelProperty(value = "备注")
@TableField(updateStrategy = FieldStrategy.ALWAYS) @TableField(updateStrategy = FieldStrategy.ALWAYS)
private String description; private String description;
/**
* 扩展字段
*/
@TableField(exist = false)
@ApiModelProperty(value = "用于子任务唯一标识", hidden = true)
private String uuid;
} }
@@ -0,0 +1,55 @@
/*
* Copyright 2021-2026 Odboy
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.odboy.system.dal.model.response;
import cn.odboy.base.KitBaseUserTimeTb;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class SystemQuartzJobVo extends KitBaseUserTimeTb {
private Long id;
@ApiModelProperty(value = "定时器名称")
private String jobName;
@ApiModelProperty(value = "Bean名称")
private String beanName;
@ApiModelProperty(value = "方法名称")
private String methodName;
@ApiModelProperty(value = "参数")
private String params;
@ApiModelProperty(value = "cron表达式")
private String cronExpression;
@ApiModelProperty(value = "状态:暂停或启动")
private Boolean isPause = false;
@ApiModelProperty(value = "负责人")
private String personInCharge;
@ApiModelProperty(value = "报警邮箱")
private String email;
@ApiModelProperty(value = "子任务")
private String subTask;
@ApiModelProperty(value = "失败后暂停")
private Boolean pauseAfterFailure;
@ApiModelProperty(value = "备注")
private String description;
/**
* 扩展字段
*/
@ApiModelProperty(value = "用于子任务唯一标识", hidden = true)
private String uuid;
}
@@ -85,10 +85,8 @@ public class SpringSecurityConfig {
.addFilterBefore(customFilter, UsernamePasswordAuthenticationFilter.class) .addFilterBefore(customFilter, UsernamePasswordAuthenticationFilter.class)
// 授权异常 // 授权异常
.exceptionHandling( .exceptionHandling(
exceptionHandling -> exceptionHandling exceptionHandling -> exceptionHandling.authenticationEntryPoint(authenticationErrorHandler)
.authenticationEntryPoint(authenticationErrorHandler) .accessDeniedHandler(jwtAccessDeniedHandler))
.accessDeniedHandler(jwtAccessDeniedHandler)
)
// 防止iframe 造成跨域 // 防止iframe 造成跨域
.headers(headers -> headers.frameOptions(HeadersConfigurer.FrameOptionsConfig::disable)) .headers(headers -> headers.frameOptions(HeadersConfigurer.FrameOptionsConfig::disable))
// 不创建会话 // 不创建会话
@@ -108,15 +106,20 @@ public class SpringSecurityConfig {
.requestMatchers(HttpMethod.OPTIONS, "/**").permitAll() .requestMatchers(HttpMethod.OPTIONS, "/**").permitAll()
// 自定义匿名访问所有url放行:允许匿名和带Token访问,细腻化到每个 Request 类型 // 自定义匿名访问所有url放行:允许匿名和带Token访问,细腻化到每个 Request 类型
// GET // GET
.requestMatchers(HttpMethod.GET, anonymousUrls.get(RequestMethodEnum.GET.getType()).toArray(new String[0])).permitAll() .requestMatchers(HttpMethod.GET,
anonymousUrls.get(RequestMethodEnum.GET.getType()).toArray(new String[0])).permitAll()
// POST // POST
.requestMatchers(HttpMethod.POST, anonymousUrls.get(RequestMethodEnum.POST.getType()).toArray(new String[0])).permitAll() .requestMatchers(HttpMethod.POST,
anonymousUrls.get(RequestMethodEnum.POST.getType()).toArray(new String[0])).permitAll()
// PUT // PUT
.requestMatchers(HttpMethod.PUT, anonymousUrls.get(RequestMethodEnum.PUT.getType()).toArray(new String[0])).permitAll() .requestMatchers(HttpMethod.PUT,
anonymousUrls.get(RequestMethodEnum.PUT.getType()).toArray(new String[0])).permitAll()
// PATCH // PATCH
.requestMatchers(HttpMethod.PATCH, anonymousUrls.get(RequestMethodEnum.PATCH.getType()).toArray(new String[0])).permitAll() .requestMatchers(HttpMethod.PATCH,
anonymousUrls.get(RequestMethodEnum.PATCH.getType()).toArray(new String[0])).permitAll()
// DELETE // DELETE
.requestMatchers(HttpMethod.DELETE, anonymousUrls.get(RequestMethodEnum.DELETE.getType()).toArray(new String[0])).permitAll() .requestMatchers(HttpMethod.DELETE,
anonymousUrls.get(RequestMethodEnum.DELETE.getType()).toArray(new String[0])).permitAll()
// 所有类型的接口都放行 // 所有类型的接口都放行
.requestMatchers(anonymousUrls.get(RequestMethodEnum.ALL.getType()).toArray(new String[0])).permitAll() .requestMatchers(anonymousUrls.get(RequestMethodEnum.ALL.getType()).toArray(new String[0])).permitAll()
// 所有请求都需要认证 // 所有请求都需要认证
@@ -0,0 +1,42 @@
/*
* Copyright 2021-2026 Odboy
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.odboy.system.framework.permission.config;
import cn.odboy.system.dal.redis.SystemUserOnlineInfoDAO;
import cn.odboy.system.framework.permission.core.handler.TokenFilter;
import cn.odboy.system.framework.permission.core.handler.TokenProvider;
import org.springframework.security.config.annotation.SecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.DefaultSecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
public class TokenConfigurer extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> {
private final TokenProvider tokenProvider;
private final SystemUserOnlineInfoDAO systemUserOnlineInfoDAO;
public TokenConfigurer(TokenProvider tokenProvider, SystemUserOnlineInfoDAO systemUserOnlineInfoDAO) {
this.tokenProvider = tokenProvider;
this.systemUserOnlineInfoDAO = systemUserOnlineInfoDAO;
}
@Override
public void configure(HttpSecurity http) {
TokenFilter customFilter = new TokenFilter(tokenProvider, systemUserOnlineInfoDAO);
http.addFilterBefore(customFilter, UsernamePasswordAuthenticationFilter.class);
}
}
@@ -23,11 +23,11 @@ import cn.odboy.system.dal.redis.SystemUserInfoDAO;
import cn.odboy.system.service.SystemDataService; import cn.odboy.system.service.SystemDataService;
import cn.odboy.system.service.SystemRoleService; import cn.odboy.system.service.SystemRoleService;
import cn.odboy.system.service.SystemUserService; import cn.odboy.system.service.SystemUserService;
import java.util.List;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.List;
/** /**
* 通过用户名判断用户信息,并获取拥有的权限与部门 * 通过用户名判断用户信息,并获取拥有的权限与部门
@@ -49,7 +49,7 @@ public class UserDetailsHandler implements UserDetailsService {
public SystemUserJwtVo loadUserByUsername(String username) { public SystemUserJwtVo loadUserByUsername(String username) {
SystemUserJwtVo userJwtVo = systemUserInfoDAO.getUserLoginInfoByUserName(username); SystemUserJwtVo userJwtVo = systemUserInfoDAO.getUserLoginInfoByUserName(username);
if (userJwtVo == null) { if (userJwtVo == null) {
SystemUserVo user = systemUserService.getUserVoWithPasswordByUsername(username); SystemUserVo user = systemUserService.getUserVoByUsername(username);
if (user == null) { if (user == null) {
throw new BadRequestException("用户不存在"); throw new BadRequestException("用户不存在");
} else { } else {
@@ -16,13 +16,15 @@
package cn.odboy.system.framework.quartz; package cn.odboy.system.framework.quartz;
import cn.odboy.system.dal.dataobject.SystemQuartzJobTb; import cn.odboy.system.dal.dataobject.SystemQuartzJobTb;
import cn.odboy.system.dal.model.response.SystemQuartzJobVo;
import cn.odboy.system.service.SystemQuartzJobService; import cn.odboy.system.service.SystemQuartzJobService;
import cn.odboy.util.KitBeanUtil;
import java.util.List;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner; import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.util.List;
@Slf4j @Slf4j
@Component @Component
@@ -41,7 +43,8 @@ public class ActiveJobRegister implements ApplicationRunner {
@Override @Override
public void run(ApplicationArguments applicationArguments) { public void run(ApplicationArguments applicationArguments) {
List<SystemQuartzJobTb> quartzJobTbs = systemQuartzJobService.listEnableQuartzJob(); List<SystemQuartzJobTb> quartzJobTbs = systemQuartzJobService.listEnableQuartzJob();
quartzJobTbs.forEach(quartzManage::addJob); List<SystemQuartzJobVo> quartzJobVos = KitBeanUtil.copyToList(quartzJobTbs, SystemQuartzJobVo.class);
quartzJobVos.forEach(quartzManage::addJob);
log.info("Timing task injection complete"); log.info("Timing task injection complete");
} }
} }
@@ -27,19 +27,19 @@ import cn.odboy.framework.redis.KitRedisHelper;
import cn.odboy.system.dal.dataobject.SystemQuartzJobTb; import cn.odboy.system.dal.dataobject.SystemQuartzJobTb;
import cn.odboy.system.dal.dataobject.SystemQuartzLogTb; import cn.odboy.system.dal.dataobject.SystemQuartzLogTb;
import cn.odboy.system.dal.model.request.SystemSendEmailArgs; import cn.odboy.system.dal.model.request.SystemSendEmailArgs;
import cn.odboy.system.dal.model.response.SystemQuartzJobVo;
import cn.odboy.system.dal.mysql.SystemQuartzLogMapper; import cn.odboy.system.dal.mysql.SystemQuartzLogMapper;
import cn.odboy.system.service.SystemEmailService; import cn.odboy.system.service.SystemEmailService;
import cn.odboy.system.service.SystemQuartzJobService; import cn.odboy.system.service.SystemQuartzJobService;
import cn.odboy.util.KitBeanUtil;
import lombok.extern.slf4j.Slf4j;
import org.quartz.JobExecutionContext;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.scheduling.quartz.QuartzJobBean;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import lombok.extern.slf4j.Slf4j;
import org.quartz.JobExecutionContext;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.scheduling.quartz.QuartzJobBean;
@Slf4j @Slf4j
public class ExecutionJobBean extends QuartzJobBean { public class ExecutionJobBean extends QuartzJobBean {
@@ -52,7 +52,7 @@ public class ExecutionJobBean extends QuartzJobBean {
@Override @Override
public void executeInternal(JobExecutionContext context) { public void executeInternal(JobExecutionContext context) {
// 获取任务 // 获取任务
SystemQuartzJobTb quartzJob = (SystemQuartzJobTb) context.getMergedJobDataMap().get(SystemQuartzJobTb.JOB_KEY); SystemQuartzJobVo quartzJob = (SystemQuartzJobVo) context.getMergedJobDataMap().get(SystemQuartzJobTb.JOB_KEY);
// 获取spring bean // 获取spring bean
SystemQuartzLogMapper quartzLogMapper = KitSpringBeanHolder.getBean(SystemQuartzLogMapper.class); SystemQuartzLogMapper quartzLogMapper = KitSpringBeanHolder.getBean(SystemQuartzLogMapper.class);
SystemQuartzJobService systemQuartzJobService = KitSpringBeanHolder.getBean(SystemQuartzJobService.class); SystemQuartzJobService systemQuartzJobService = KitSpringBeanHolder.getBean(SystemQuartzJobService.class);
@@ -99,8 +99,7 @@ public class ExecutionJobBean extends QuartzJobBean {
if (quartzJob.getPauseAfterFailure() != null && quartzJob.getPauseAfterFailure()) { if (quartzJob.getPauseAfterFailure() != null && quartzJob.getPauseAfterFailure()) {
quartzJob.setIsPause(false); quartzJob.setIsPause(false);
// 更新状态 // 更新状态
SystemQuartzJobTb quartzJobTb = KitBeanUtil.copyToClass(quartzJob, SystemQuartzJobTb.class); systemQuartzJobService.switchQuartzJobStatus(quartzJob);
systemQuartzJobService.switchQuartzJobStatus(quartzJobTb);
} }
if (quartzJob.getEmail() != null) { if (quartzJob.getEmail() != null) {
SystemEmailService emailService = KitSpringBeanHolder.getBean(SystemEmailService.class); SystemEmailService emailService = KitSpringBeanHolder.getBean(SystemEmailService.class);
@@ -115,7 +114,7 @@ public class ExecutionJobBean extends QuartzJobBean {
} }
} }
private SystemSendEmailArgs taskAlarm(SystemQuartzJobTb quartzJob, String msg) { private SystemSendEmailArgs taskAlarm(SystemQuartzJobVo quartzJob, String msg) {
SystemSendEmailArgs sendEmailRequest = new SystemSendEmailArgs(); SystemSendEmailArgs sendEmailRequest = new SystemSendEmailArgs();
sendEmailRequest.setSubject("定时任务【" + quartzJob.getJobName() + "】执行失败,请尽快处理!"); sendEmailRequest.setSubject("定时任务【" + quartzJob.getJobName() + "】执行失败,请尽快处理!");
Map<String, Object> data = new HashMap<>(16); Map<String, Object> data = new HashMap<>(16);
@@ -17,6 +17,9 @@ package cn.odboy.system.framework.quartz;
import cn.odboy.framework.exception.BadRequestException; import cn.odboy.framework.exception.BadRequestException;
import cn.odboy.system.dal.dataobject.SystemQuartzJobTb; import cn.odboy.system.dal.dataobject.SystemQuartzJobTb;
import cn.odboy.system.dal.model.response.SystemQuartzJobVo;
import cn.odboy.util.KitBeanUtil;
import java.util.Date;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.quartz.CronScheduleBuilder; import org.quartz.CronScheduleBuilder;
@@ -32,7 +35,6 @@ import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey; import org.quartz.TriggerKey;
import org.quartz.impl.triggers.CronTriggerImpl; import org.quartz.impl.triggers.CronTriggerImpl;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.util.Date;
@Slf4j @Slf4j
@Component @Component
@@ -42,7 +44,7 @@ public class QuartzManage {
@Resource @Resource
private Scheduler scheduler; private Scheduler scheduler;
public void addJob(SystemQuartzJobTb quartzJob) { public void addJob(SystemQuartzJobVo quartzJob) {
try { try {
String uuid = JOB_NAME + quartzJob.getId(); String uuid = JOB_NAME + quartzJob.getId();
// 构建job信息 // 构建job信息
@@ -81,22 +83,23 @@ public class QuartzManage {
*/ */
public void updateJobCron(SystemQuartzJobTb quartzJob) { public void updateJobCron(SystemQuartzJobTb quartzJob) {
try { try {
TriggerKey triggerKey = TriggerKey.triggerKey(JOB_NAME + quartzJob.getId()); SystemQuartzJobVo quartzJobVo = KitBeanUtil.copyToClass(quartzJob, SystemQuartzJobVo.class);
TriggerKey triggerKey = TriggerKey.triggerKey(JOB_NAME + quartzJobVo.getId());
CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey); CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
// 如果不存在则创建一个定时任务 // 如果不存在则创建一个定时任务
if (trigger == null) { if (trigger == null) {
addJob(quartzJob); addJob(quartzJobVo);
trigger = (CronTrigger) scheduler.getTrigger(triggerKey); trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
} }
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(quartzJob.getCronExpression()); CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(quartzJobVo.getCronExpression());
trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build(); trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
// 重置启动时间 // 重置启动时间
((CronTriggerImpl) trigger).setStartTime(new Date()); ((CronTriggerImpl) trigger).setStartTime(new Date());
trigger.getJobDataMap().put(SystemQuartzJobTb.JOB_KEY, quartzJob); trigger.getJobDataMap().put(SystemQuartzJobTb.JOB_KEY, quartzJobVo);
scheduler.rescheduleJob(triggerKey, trigger); scheduler.rescheduleJob(triggerKey, trigger);
// 暂停任务 // 暂停任务
if (quartzJob.getIsPause()) { if (quartzJobVo.getIsPause()) {
pauseJob(quartzJob); pauseJob(quartzJobVo);
} }
} catch (Exception e) { } catch (Exception e) {
log.error("更新定时任务失败", e); log.error("更新定时任务失败", e);
@@ -125,7 +128,7 @@ public class QuartzManage {
* *
* @param quartzJob / * @param quartzJob /
*/ */
public void resumeJob(SystemQuartzJobTb quartzJob) { public void resumeJob(SystemQuartzJobVo quartzJob) {
try { try {
TriggerKey triggerKey = TriggerKey.triggerKey(JOB_NAME + quartzJob.getId()); TriggerKey triggerKey = TriggerKey.triggerKey(JOB_NAME + quartzJob.getId());
CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey); CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
@@ -146,7 +149,7 @@ public class QuartzManage {
* *
* @param quartzJob / * @param quartzJob /
*/ */
public void runJobNow(SystemQuartzJobTb quartzJob) { public void runJobNow(SystemQuartzJobVo quartzJob) {
try { try {
String uuid = JOB_NAME + quartzJob.getId(); String uuid = JOB_NAME + quartzJob.getId();
TriggerKey triggerKey = TriggerKey.triggerKey(uuid); TriggerKey triggerKey = TriggerKey.triggerKey(uuid);
@@ -170,7 +173,7 @@ public class QuartzManage {
* *
* @param quartzJob / * @param quartzJob /
*/ */
public void pauseJob(SystemQuartzJobTb quartzJob) { public void pauseJob(SystemQuartzJobVo quartzJob) {
try { try {
JobKey jobKey = JobKey.jobKey(JOB_NAME + quartzJob.getId()); JobKey jobKey = JobKey.jobKey(JOB_NAME + quartzJob.getId());
scheduler.pauseJob(jobKey); scheduler.pauseJob(jobKey);
@@ -16,6 +16,7 @@
package cn.odboy.system.service; package cn.odboy.system.service;
import cn.odboy.constant.SystemConst; import cn.odboy.constant.SystemConst;
import cn.odboy.framework.exception.BadRequestException;
import cn.odboy.framework.properties.AppProperties; import cn.odboy.framework.properties.AppProperties;
import cn.odboy.system.dal.model.request.SystemUserLoginArgs; import cn.odboy.system.dal.model.request.SystemUserLoginArgs;
import cn.odboy.system.dal.model.response.SystemAuthVo; import cn.odboy.system.dal.model.response.SystemAuthVo;
@@ -56,23 +57,25 @@ public class SystemAuthService {
private SystemCaptchaService systemCaptchaService; private SystemCaptchaService systemCaptchaService;
/** /**
* 登录 * 登录 -> TestPassed
* *
* @param loginArgs / * @param loginArgs /
* @param request / * @param request /
*/ */
public SystemAuthVo doLogin(SystemUserLoginArgs loginArgs, HttpServletRequest request) throws Exception { public SystemAuthVo doLogin(SystemUserLoginArgs loginArgs, HttpServletRequest request) throws Exception {
KitValidUtil.isNull(loginArgs); KitValidUtil.notNull(loginArgs);
// 密码解密 // 密码解密
String password = KitRsaEncryptUtil.decryptByPrivateKey(properties.getRsa().getPrivateKey(), loginArgs.getPassword()); String password =
KitRsaEncryptUtil.decryptByPrivateKey(properties.getRsa().getPrivateKey(), loginArgs.getPassword());
// 校验验证码 // 校验验证码
systemCaptchaService.validate(loginArgs.getUuid(), loginArgs.getCode()); systemCaptchaService.validate(loginArgs.getUuid(), loginArgs.getCode());
// 查询用户信息 // 查询用户信息
SystemUserJwtVo jwtUser = userDetailsService.loadUserByUsername(loginArgs.getUsername()); SystemUserJwtVo jwtUser = userDetailsService.loadUserByUsername(loginArgs.getUsername());
// 验证用户密码 // 验证用户密码
KitValidUtil.isTrue(!passwordEncoder.matches(password, jwtUser.getPassword()), "登录密码错误"); if (!passwordEncoder.matches(password, jwtUser.getPassword())) {
throw new BadRequestException("登录密码错误");
}
// 登录验证 // 登录验证
Authentication authentication = Authentication authentication =
@@ -98,7 +101,7 @@ public class SystemAuthService {
} }
/** /**
* 查询当前登录人信息 * 查询当前登录人信息 -> TestPassed
*/ */
public SystemUserJwtVo getCurrentUserInfo() { public SystemUserJwtVo getCurrentUserInfo() {
SystemUserJwtVo jwtUser = (SystemUserJwtVo) KitSecurityHelper.getCurrentUser(); SystemUserJwtVo jwtUser = (SystemUserJwtVo) KitSecurityHelper.getCurrentUser();
@@ -109,7 +112,7 @@ public class SystemAuthService {
} }
/** /**
* 退出登录 * 退出登录 -> TestPassed
* *
* @param request / * @param request /
*/ */
@@ -19,11 +19,11 @@ import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import cn.odboy.constant.CaptchaCodeEnum; import cn.odboy.constant.CaptchaCodeEnum;
import cn.odboy.constant.SystemConst; import cn.odboy.constant.SystemConst;
import cn.odboy.framework.exception.BadRequestException;
import cn.odboy.framework.properties.AppProperties; import cn.odboy.framework.properties.AppProperties;
import cn.odboy.framework.redis.KitRedisHelper; import cn.odboy.framework.redis.KitRedisHelper;
import cn.odboy.system.constant.SystemCacheKey; import cn.odboy.system.constant.SystemCacheKey;
import cn.odboy.system.dal.model.response.SystemCaptchaVo; import cn.odboy.system.dal.model.response.SystemCaptchaVo;
import cn.odboy.util.KitValidUtil;
import com.wf.captcha.base.Captcha; import com.wf.captcha.base.Captcha;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@@ -41,7 +41,7 @@ public class SystemCaptchaService {
private AppProperties properties; private AppProperties properties;
/** /**
* 查询登录验证码 * 查询登录验证码 -> TestPassed
*/ */
public SystemCaptchaVo getLoginCaptcha() { public SystemCaptchaVo getLoginCaptcha() {
// 查询运算的结果 // 查询运算的结果
@@ -63,7 +63,7 @@ public class SystemCaptchaService {
} }
/** /**
* 验证验证码 * 验证验证码 -> TestPassed
* *
* @param uuid 验证码uuid * @param uuid 验证码uuid
* @param inputCode 用户输入的验证码 * @param inputCode 用户输入的验证码
@@ -71,9 +71,13 @@ public class SystemCaptchaService {
public void validate(String uuid, String inputCode) { public void validate(String uuid, String inputCode) {
// 查询验证码 // 查询验证码
String code = redisHelper.get(uuid, String.class); String code = redisHelper.get(uuid, String.class);
KitValidUtil.isBlank(code, "验证码不存在或已过期"); if (StrUtil.isBlank(code)) {
throw new BadRequestException("验证码不存在或已过期");
}
// 清除验证码 // 清除验证码
redisHelper.del(uuid); redisHelper.del(uuid);
KitValidUtil.isTrue(StrUtil.isBlank(inputCode) || !code.equalsIgnoreCase(inputCode), "验证码错误"); if (StrUtil.isBlank(inputCode) || !code.equalsIgnoreCase(inputCode)) {
throw new BadRequestException("验证码错误");
}
} }
} }
@@ -45,7 +45,7 @@ public class SystemDataService {
private SystemRoleDeptService systemRoleDeptService; private SystemRoleDeptService systemRoleDeptService;
/** /**
* 查询数据权限 * 查询数据权限 -> TestPassed
* *
* @param user / * @param user /
* @return / * @return /
@@ -75,7 +75,7 @@ public class SystemDataService {
} }
/** /**
* 查询自定义的数据权限 * 查询自定义的数据权限 -> TestPassed
* *
* @param deptIds 部门ID(外部数据) * @param deptIds 部门ID(外部数据)
* @param roleId 角色ID * @param roleId 角色ID
@@ -34,10 +34,10 @@ import cn.odboy.util.KitClassUtil;
import cn.odboy.util.KitValidUtil; import cn.odboy.util.KitValidUtil;
import cn.odboy.util.xlsx.KitExcelExporter; import cn.odboy.util.xlsx.KitExcelExporter;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import jakarta.servlet.http.HttpServletResponse;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
@@ -58,13 +58,13 @@ public class SystemDeptService {
private SystemRoleDeptService systemRoleDeptService; private SystemRoleDeptService systemRoleDeptService;
/** /**
* 创建 * 创建 -> TestPassed
* *
* @param args / * @param args /
*/ */
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void saveDept(SystemCreateDeptArgs args) { public void saveDept(SystemCreateDeptArgs args) {
KitValidUtil.isNull(args); KitValidUtil.notNull(args);
SystemDeptTb record = KitBeanUtil.copyToClass(args, SystemDeptTb.class); SystemDeptTb record = KitBeanUtil.copyToClass(args, SystemDeptTb.class);
systemDeptMapper.insert(record); systemDeptMapper.insert(record);
@@ -73,13 +73,13 @@ public class SystemDeptService {
} }
/** /**
* 编辑 * 编辑 -> TestPassed
* *
* @param args / * @param args /
*/ */
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void updateDeptById(SystemDeptTb args) { public void updateDeptById(SystemDeptTb args) {
KitValidUtil.isNull(args); KitValidUtil.notNull(args);
// 旧的父部门 // 旧的父部门
Long oldPid = this.getDeptById(args.getId()).getPid(); Long oldPid = this.getDeptById(args.getId()).getPid();
// 新的父部门 // 新的父部门
@@ -104,9 +104,7 @@ public class SystemDeptService {
// 查询部门, 和其所有子部门 // 查询部门, 和其所有子部门
Set<SystemDeptTb> depts = this.traverseDeptByIdWithPids(ids); Set<SystemDeptTb> depts = this.traverseDeptByIdWithPids(ids);
// 验证是否被角色或用户关联 // 验证是否被角色或用户关联
Set<Long> deptIds = depts.stream().map(SystemDeptTb::getId).collect(Collectors.toSet()); this.verifyBindRelationByIds(depts);
KitValidUtil.isTrue(systemUserDeptService.countUserByDeptIds(deptIds) > 0, "所选部门存在用户关联,请解除后再试");
KitValidUtil.isTrue(systemRoleDeptService.countRoleByDeptIds(deptIds) > 0, "所选部门存在角色关联,请解除后再试");
for (SystemDeptTb dept : depts) { for (SystemDeptTb dept : depts) {
systemDeptMapper.deleteById(dept.getId()); systemDeptMapper.deleteById(dept.getId());
this.updateDeptSubCnt(dept.getPid()); this.updateDeptSubCnt(dept.getPid());
@@ -114,7 +112,7 @@ public class SystemDeptService {
} }
/** /**
* 更新父节点中子节点数目 * 更新父节点中子节点数目 -> TestPassed
* *
* @param deptId 部门id * @param deptId 部门id
*/ */
@@ -254,6 +252,21 @@ public class SystemDeptService {
return systemDeptMapper.selectList(wrapper).stream().collect(Collectors.toMap(SystemDeptTb::getId, i -> i, (m, n) -> m)); return systemDeptMapper.selectList(wrapper).stream().collect(Collectors.toMap(SystemDeptTb::getId, i -> i, (m, n) -> m));
} }
/**
* 验证是否被角色或用户关联
*
* @param deptSet /
*/
public void verifyBindRelationByIds(Set<SystemDeptTb> deptSet) {
Set<Long> deptIds = deptSet.stream().map(SystemDeptTb::getId).collect(Collectors.toSet());
if (systemUserDeptService.countUserByDeptIds(deptIds) > 0) {
throw new BadRequestException("所选部门存在用户关联,请解除后再试!");
}
if (systemRoleDeptService.countRoleByDeptIds(deptIds) > 0) {
throw new BadRequestException("所选部门存在角色关联,请解除后再试!");
}
}
/** /**
* 根据部门id遍历所有部门和子部门 * 根据部门id遍历所有部门和子部门
* *
@@ -361,7 +374,7 @@ public class SystemDeptService {
} }
/** /**
* 根据部门id查询部门信息 * 根据部门id查询部门信息 -> TestPassed
* *
* @param id 部门id * @param id 部门id
* @return / * @return /
@@ -49,21 +49,21 @@ public class SystemDictDetailService {
private SystemDictMapper systemDictMapper; private SystemDictMapper systemDictMapper;
/** /**
* 创建 * 创建 -> TestPassed
* *
* @param args / * @param args /
*/ */
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void saveDictDetail(SystemCreateDictDetailArgs args) { public void saveDictDetail(SystemCreateDictDetailArgs args) {
KitValidUtil.isNull(args); KitValidUtil.notNull(args);
KitValidUtil.isNull(args.getDict()); KitValidUtil.notNull(args.getDict());
SystemDictDetailTb dictDetail = KitBeanUtil.copyToClass(args, SystemDictDetailTb.class); SystemDictDetailTb dictDetail = KitBeanUtil.copyToClass(args, SystemDictDetailTb.class);
dictDetail.setDictId(args.getDict().getId()); dictDetail.setDictId(args.getDict().getId());
systemDictDetailMapper.insert(dictDetail); systemDictDetailMapper.insert(dictDetail);
} }
/** /**
* 编辑 * 编辑 -> TestPassed
* *
* @param args / * @param args /
*/ */
@@ -71,11 +71,11 @@ public class SystemDictDetailService {
public void updateDictDetailById(SystemDictDetailTb args) { public void updateDictDetailById(SystemDictDetailTb args) {
SystemDictDetailTb dictDetail = systemDictDetailMapper.selectById(args.getId()); SystemDictDetailTb dictDetail = systemDictDetailMapper.selectById(args.getId());
args.setId(dictDetail.getId()); args.setId(dictDetail.getId());
systemDictDetailMapper.updateById(args); systemDictDetailMapper.insertOrUpdate(args);
} }
/** /**
* 删除 * 删除 -> TestPassed
* *
* @param id / * @param id /
*/ */
@@ -99,7 +99,7 @@ public class SystemDictDetailService {
} }
/** /**
* 分页查询 * 分页查询 -> TestPassed
* *
* @param args 条件 * @param args 条件
* @param page 分页参数 * @param page 分页参数
@@ -123,7 +123,7 @@ public class SystemDictDetailService {
} }
/** /**
* 根据字典名称查询字典详情 * 根据字典名称查询字典详情 -> TestPassed
* *
* @param name 字典名称 * @param name 字典名称
* @return / * @return /
@@ -46,7 +46,7 @@ public class SystemDictService {
private SystemDictDetailService systemDictDetailService; private SystemDictDetailService systemDictDetailService;
/** /**
* 创建 * 创建 -> TestPassed
* *
* @param args / * @param args /
*/ */
@@ -57,7 +57,7 @@ public class SystemDictService {
} }
/** /**
* 编辑 * 编辑 -> TestPassed
* *
* @param args / * @param args /
*/ */
@@ -70,7 +70,7 @@ public class SystemDictService {
} }
/** /**
* 删除 * 删除 -> TestPassed
* *
* @param ids / * @param ids /
*/ */
@@ -83,7 +83,7 @@ public class SystemDictService {
} }
/** /**
* 分页查询 * 分页查询 -> TestPassed
* *
* @param args 条件 * @param args 条件
* @param page 分页参数 * @param page 分页参数
@@ -30,7 +30,6 @@ import cn.odboy.system.dal.model.request.SystemSendEmailArgs;
import cn.odboy.system.dal.mysql.SystemEmailConfigMapper; import cn.odboy.system.dal.mysql.SystemEmailConfigMapper;
import cn.odboy.util.KitDesEncryptUtil; import cn.odboy.util.KitDesEncryptUtil;
import cn.odboy.util.KitResourceTemplateUtil; import cn.odboy.util.KitResourceTemplateUtil;
import cn.odboy.util.KitValidUtil;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@@ -49,7 +48,7 @@ public class SystemEmailService {
private AppProperties properties; private AppProperties properties;
/** /**
* 更新邮件配置 * 更新邮件配置 -> TestPassed
* *
* @param emailConfig 邮箱配置 * @param emailConfig 邮箱配置
*/ */
@@ -65,13 +64,15 @@ public class SystemEmailService {
} }
/** /**
* 发送邮件 * 发送邮件 -> TestPassed
* *
* @param sendEmailRequest 邮件发送的内容 * @param sendEmailRequest 邮件发送的内容
*/ */
public void sendEmail(SystemSendEmailArgs sendEmailRequest) { public void sendEmail(SystemSendEmailArgs sendEmailRequest) {
SystemEmailConfigTb systemEmailConfigTb = getLastEmailConfig(); SystemEmailConfigTb systemEmailConfigTb = getLastEmailConfig();
KitValidUtil.isNull(systemEmailConfigTb.getId(), "请先配置, 再操作"); if (systemEmailConfigTb.getId() == null) {
throw new BadRequestException("请先配置, 再操作");
}
// 封装 // 封装
MailAccount account = new MailAccount(); MailAccount account = new MailAccount();
// 设置用户 // 设置用户
@@ -111,18 +112,23 @@ public class SystemEmailService {
* 发送给邮箱验证码 * 发送给邮箱验证码
*/ */
public void sendCaptcha(SystemCaptchaBizEnum biEnum, String email) { public void sendCaptcha(SystemCaptchaBizEnum biEnum, String email) {
KitValidUtil.isNull(biEnum, "biEnum必填"); if (biEnum == null) {
throw new BadRequestException("biEnum必填");
}
String content; String content;
String redisKey = biEnum.getRedisKey() + email; String redisKey = biEnum.getRedisKey() + email;
String oldCode = redisHelper.get(redisKey, String.class); String oldCode = redisHelper.get(redisKey, String.class);
if (oldCode == null) { if (oldCode == null) {
String code = RandomUtil.randomNumbers(6); String code = RandomUtil.randomNumbers(6);
// 存入缓存 // 存入缓存
KitValidUtil.isTrue(!redisHelper.set(redisKey, code, properties.getCaptcha().getExpireTime()), "服务异常, 请联系网站负责人"); if (!redisHelper.set(redisKey, code, properties.getCaptcha().getExpireTime())) {
throw new BadRequestException("服务异常, 请联系网站负责人");
}
// 存在就再次发送原来的验证码 // 存在就再次发送原来的验证码
content = KitResourceTemplateUtil.render(null, biEnum.getTemplateName(), Dict.create().set("code", code)); content = KitResourceTemplateUtil.render(null, biEnum.getTemplateName(), Dict.create().set("code", code));
} else { } else {
content = KitResourceTemplateUtil.render(null, biEnum.getTemplateName(), Dict.create().set("code", oldCode)); content =
KitResourceTemplateUtil.render(null, biEnum.getTemplateName(), Dict.create().set("code", oldCode));
} }
SystemSendEmailArgs sendEmailRequest = SystemSendEmailArgs sendEmailRequest =
new SystemSendEmailArgs(Collections.singletonList(email), SystemConst.CURRENT_APP_TITLE, content); new SystemSendEmailArgs(Collections.singletonList(email), SystemConst.CURRENT_APP_TITLE, content);
@@ -140,18 +146,23 @@ public class SystemEmailService {
} }
/** /**
* 校验邮箱验证码 * 校验邮箱验证码 -> TestPassed
*/ */
public void checkEmailCaptcha(SystemCheckEmailCaptchaArgs args) { public void checkEmailCaptcha(SystemCheckEmailCaptchaArgs args) {
SystemCaptchaBizEnum biEnum = SystemCaptchaBizEnum.getByBizCode(args.getBizCode()); SystemCaptchaBizEnum biEnum = SystemCaptchaBizEnum.getByBizCode(args.getBizCode());
KitValidUtil.isNull(biEnum, "不支持的业务"); if (biEnum == null) {
throw new BadRequestException("不支持的业务");
}
this.checkEmailCaptchaV1(biEnum, args.getEmail(), args.getCode()); this.checkEmailCaptchaV1(biEnum, args.getEmail(), args.getCode());
} }
public void checkEmailCaptchaV1(SystemCaptchaBizEnum biEnum, String email, String code) { public void checkEmailCaptchaV1(SystemCaptchaBizEnum biEnum, String email, String code) {
String redisKey = biEnum.getRedisKey() + email; String redisKey = biEnum.getRedisKey() + email;
String value = redisHelper.get(redisKey, String.class); String value = redisHelper.get(redisKey, String.class);
KitValidUtil.isTrue(value == null || !value.equals(code), "无效验证码"); if (value == null || !value.equals(code)) {
throw new BadRequestException("无效验证码");
} else {
redisHelper.del(redisKey); redisHelper.del(redisKey);
} }
} }
}
@@ -18,6 +18,7 @@ package cn.odboy.system.service;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import cn.odboy.base.KitPageResult; import cn.odboy.base.KitPageResult;
import cn.odboy.framework.exception.BadRequestException;
import cn.odboy.system.dal.dataobject.SystemJobTb; import cn.odboy.system.dal.dataobject.SystemJobTb;
import cn.odboy.system.dal.model.export.SystemJobExportRowVo; import cn.odboy.system.dal.model.export.SystemJobExportRowVo;
import cn.odboy.system.dal.model.request.SystemCreateJobArgs; import cn.odboy.system.dal.model.request.SystemCreateJobArgs;
@@ -25,7 +26,6 @@ import cn.odboy.system.dal.model.request.SystemQueryJobArgs;
import cn.odboy.system.dal.mysql.SystemJobMapper; import cn.odboy.system.dal.mysql.SystemJobMapper;
import cn.odboy.util.KitBeanUtil; import cn.odboy.util.KitBeanUtil;
import cn.odboy.util.KitPageUtil; import cn.odboy.util.KitPageUtil;
import cn.odboy.util.KitValidUtil;
import cn.odboy.util.xlsx.KitExcelExporter; import cn.odboy.util.xlsx.KitExcelExporter;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@@ -46,44 +46,48 @@ public class SystemJobService {
private SystemUserJobService systemUserJobService; private SystemUserJobService systemUserJobService;
/** /**
* 创建 * 创建 -> TestPassed
* *
* @param args / * @param args /
*/ */
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void saveJob(SystemCreateJobArgs args) { public void saveJob(SystemCreateJobArgs args) {
KitValidUtil.isTrue(this.existJobWithName(args.getName()), "职位名称已存在"); if (this.existJobWithName(args.getName())) {
throw new BadRequestException("职位名称已存在");
}
SystemJobTb systemJobTb = KitBeanUtil.copyToClass(args, SystemJobTb.class); SystemJobTb systemJobTb = KitBeanUtil.copyToClass(args, SystemJobTb.class);
systemJobMapper.insert(systemJobTb); systemJobMapper.insert(systemJobTb);
} }
/** /**
* 编辑 * 编辑 -> TestPassed
* *
* @param args / * @param args /
*/ */
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void updateJobById(SystemJobTb args) { public void updateJobById(SystemJobTb args) {
SystemJobTb job = systemJobMapper.selectById(args.getId()); SystemJobTb job = systemJobMapper.selectById(args.getId());
KitValidUtil.isTrue(this.existJobWithNameNeSelf(args.getName(), job.getId()), "职位名称已存在"); if (this.existJobWithNameNeSelf(args.getName(), job.getId())) {
throw new BadRequestException("职位名称已存在");
}
args.setId(job.getId()); args.setId(job.getId());
systemJobMapper.updateById(args); systemJobMapper.updateById(args);
} }
/** /**
* 删除 * 删除 -> TestPassed
* *
* @param ids / * @param ids /
*/ */
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void deleteJobByIds(Set<Long> ids) { public void deleteJobByIds(Set<Long> ids) {
// 验证是否被用户关联 // 验证是否被用户关联
KitValidUtil.isTrue(systemUserJobService.countUserByJobIds(ids) > 0, "所选的岗位中存在用户关联, 请解除关联再试"); this.verifyBindRelationByIds(ids);
systemJobMapper.deleteByIds(ids); systemJobMapper.deleteByIds(ids);
} }
/** /**
* 分页查询 * 分页查询 -> TestPassed
* *
* @param args 条件 * @param args 条件
* @param page 分页参数 * @param page 分页参数
@@ -96,7 +100,7 @@ public class SystemJobService {
} }
/** /**
* 查询全部数据 * 查询全部数据 -> TestPassed
*/ */
public List<SystemJobTb> queryJobByArgs(SystemQueryJobArgs args) { public List<SystemJobTb> queryJobByArgs(SystemQueryJobArgs args) {
LambdaQueryWrapper<SystemJobTb> wrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<SystemJobTb> wrapper = new LambdaQueryWrapper<>();
@@ -105,7 +109,18 @@ public class SystemJobService {
} }
/** /**
* 导出岗位数据 * 验证是否被用户关联 -> TestPassed
*
* @param ids /
*/
public void verifyBindRelationByIds(Set<Long> ids) {
if (systemUserJobService.countUserByJobIds(ids) > 0) {
throw new BadRequestException("所选的岗位中存在用户关联, 请解除关联再试!");
}
}
/**
* 导出岗位数据 -> TestPassed
*/ */
public void exportJobXlsx(HttpServletResponse response, SystemQueryJobArgs args) { public void exportJobXlsx(HttpServletResponse response, SystemQueryJobArgs args) {
List<SystemJobTb> systemJobTbs = this.queryJobByArgs(args); List<SystemJobTb> systemJobTbs = this.queryJobByArgs(args);
@@ -121,7 +136,7 @@ public class SystemJobService {
} }
/** /**
* 根据岗位名称查询岗位是否存在 * 根据岗位名称查询岗位是否存在 -> TestPassed
*/ */
private boolean existJobWithName(String name) { private boolean existJobWithName(String name) {
LambdaQueryWrapper<SystemJobTb> wrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<SystemJobTb> wrapper = new LambdaQueryWrapper<>();
@@ -130,7 +145,7 @@ public class SystemJobService {
} }
/** /**
* 根据岗位名称和岗位id查询岗位是否存在 * 根据岗位名称和岗位id查询岗位是否存在 -> TestPassed
*/ */
private boolean existJobWithNameNeSelf(String name, Long currentJobId) { private boolean existJobWithNameNeSelf(String name, Long currentJobId) {
LambdaQueryWrapper<SystemJobTb> wrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<SystemJobTb> wrapper = new LambdaQueryWrapper<>();
@@ -32,7 +32,6 @@ import cn.odboy.system.dal.mysql.SystemLocalStorageMapper;
import cn.odboy.util.KitBeanUtil; import cn.odboy.util.KitBeanUtil;
import cn.odboy.util.KitFileUtil; import cn.odboy.util.KitFileUtil;
import cn.odboy.util.KitPageUtil; import cn.odboy.util.KitPageUtil;
import cn.odboy.util.KitValidUtil;
import cn.odboy.util.xlsx.KitExcelExporter; import cn.odboy.util.xlsx.KitExcelExporter;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@@ -62,7 +61,7 @@ public class SystemLocalStorageService {
private SystemLocalStorageService localStorageService; private SystemLocalStorageService localStorageService;
/** /**
* 上传 * 上传 -> TestPassed
* *
* @param name 文件名称 * @param name 文件名称
* @param multipartFile 文件 * @param multipartFile 文件
@@ -76,7 +75,9 @@ public class SystemLocalStorageService {
String type = KitFileUtil.getFileType(suffix); String type = KitFileUtil.getFileType(suffix);
String uploadDateStr = DateUtil.format(new Date(), DatePattern.PURE_DATE_FORMAT); String uploadDateStr = DateUtil.format(new Date(), DatePattern.PURE_DATE_FORMAT);
File file = KitFileUtil.upload(multipartFile, fileUploadPathHelper.getPath() + uploadDateStr + File.separator); File file = KitFileUtil.upload(multipartFile, fileUploadPathHelper.getPath() + uploadDateStr + File.separator);
KitValidUtil.isNull(file, "上传失败"); if (file == null) {
throw new BadRequestException("上传失败");
}
try { try {
String formatSize = KitFileUtil.getSize(size); String formatSize = KitFileUtil.getSize(size);
String prefixName = KitFileUtil.getPrefix(multipartFile.getOriginalFilename(), name); String prefixName = KitFileUtil.getPrefix(multipartFile.getOriginalFilename(), name);
@@ -98,7 +99,7 @@ public class SystemLocalStorageService {
} }
/** /**
* 编辑 * 编辑 -> TestPassed
* *
* @param args 文件信息 * @param args 文件信息
*/ */
@@ -108,7 +109,7 @@ public class SystemLocalStorageService {
} }
/** /**
* 多选删除 * 多选删除 -> TestPassed
* *
* @param ids / * @param ids /
*/ */
@@ -126,7 +127,7 @@ public class SystemLocalStorageService {
} }
/** /**
* 分页查询 * 分页查询 -> TestPassed
* *
* @param args 条件 * @param args 条件
* @param page 分页参数 * @param page 分页参数
@@ -140,7 +141,7 @@ public class SystemLocalStorageService {
} }
/** /**
* 查询文件上传记录 * 查询文件上传记录 -> TestPassed
*/ */
public List<SystemLocalStorageTb> queryLocalStorageByArgs(SystemQueryStorageArgs args) { public List<SystemLocalStorageTb> queryLocalStorageByArgs(SystemQueryStorageArgs args) {
LambdaQueryWrapper<SystemLocalStorageTb> wrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<SystemLocalStorageTb> wrapper = new LambdaQueryWrapper<>();
@@ -149,18 +150,20 @@ public class SystemLocalStorageService {
} }
/** /**
* 上传图片 * 上传图片 -> TestPassed
*/ */
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public SystemLocalStorageTb uploadPicture(MultipartFile file) { public SystemLocalStorageTb uploadPicture(MultipartFile file) {
// 判断文件是否为图片 // 判断文件是否为图片
String suffix = KitFileUtil.getSuffix(file.getOriginalFilename()); String suffix = KitFileUtil.getSuffix(file.getOriginalFilename());
KitValidUtil.isTrue(!FileTypeEnum.IMAGE.getCode().equals(KitFileUtil.getFileType(suffix)), "只能上传图片"); if (!FileTypeEnum.IMAGE.getCode().equals(KitFileUtil.getFileType(suffix))) {
throw new BadRequestException("只能上传图片");
}
return localStorageService.uploadFile(null, file); return localStorageService.uploadFile(null, file);
} }
/** /**
* 导出文件上传记录 * 导出文件上传记录 -> TestPassed
*/ */
public void exportLocalStorageXlsx(HttpServletResponse response, SystemQueryStorageArgs args) { public void exportLocalStorageXlsx(HttpServletResponse response, SystemQueryStorageArgs args) {
List<SystemLocalStorageTb> systemLocalStorageTbs = this.queryLocalStorageByArgs(args); List<SystemLocalStorageTb> systemLocalStorageTbs = this.queryLocalStorageByArgs(args);
@@ -64,15 +64,19 @@ public class SystemMenuService {
private SystemMenuService proxyService; private SystemMenuService proxyService;
/** /**
* 创建 * 创建 -> TestPassed
* *
* @param args / * @param args /
*/ */
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void saveMenu(SystemMenuTb args) { public void saveMenu(SystemMenuTb args) {
KitValidUtil.isTrue(this.existMenuWithTitle(args.getTitle()), "菜单标题已存在"); if (this.existMenuWithTitle(args.getTitle())) {
throw new BadRequestException("菜单标题已存在");
}
if (StrUtil.isNotBlank(args.getComponentName())) { if (StrUtil.isNotBlank(args.getComponentName())) {
KitValidUtil.isTrue(this.existMenuWithComponentName(args.getComponentName()), "菜单组件名称已存在"); if (this.existMenuWithComponentName(args.getComponentName())) {
throw new BadRequestException("菜单组件名称已存在");
}
} }
if (Long.valueOf(0L).equals(args.getPid())) { if (Long.valueOf(0L).equals(args.getPid())) {
// 顶级目录 // 顶级目录
@@ -92,20 +96,25 @@ public class SystemMenuService {
} }
/** /**
* 编辑 * 编辑 -> TestPassed
* *
* @param args / * @param args /
*/ */
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void updateMenuById(SystemMenuTb args) { public void updateMenuById(SystemMenuTb args) {
KitValidUtil.isNullF(args.getId(), "id"); if (args.getId().equals(args.getPid())) {
KitValidUtil.isTrue(args.getId().equals(args.getPid()), "上级不能为自己"); throw new BadRequestException("上级不能为自己");
}
SystemMenuTb menu = systemMenuMapper.selectById(args.getId()); SystemMenuTb menu = systemMenuMapper.selectById(args.getId());
if (args.getIFrame()) { if (args.getIFrame()) {
KitValidUtil.isTrue(!(args.getPath().toLowerCase().startsWith(SystemTransferProtocolConst.PREFIX_HTTP) || args.getPath() if (!(args.getPath().toLowerCase().startsWith(SystemTransferProtocolConst.PREFIX_HTTP) || args.getPath()
.toLowerCase().startsWith(SystemTransferProtocolConst.PREFIX_HTTPS)), SystemTransferProtocolConst.PREFIX_HTTPS_BAD_REQUEST); .toLowerCase().startsWith(SystemTransferProtocolConst.PREFIX_HTTPS))) {
throw new BadRequestException(SystemTransferProtocolConst.PREFIX_HTTPS_BAD_REQUEST);
}
}
if (this.existMenuWithTitleNeSelf(args.getTitle(), menu.getId())) {
throw new BadRequestException("菜单标题已存在");
} }
KitValidUtil.isTrue(this.existMenuWithTitleNeSelf(args.getTitle(), menu.getId()), "菜单标题已存在");
if (args.getPid().equals(0L)) { if (args.getPid().equals(0L)) {
args.setPid(null); args.setPid(null);
} }
@@ -113,7 +122,9 @@ public class SystemMenuService {
Long oldPid = menu.getPid(); Long oldPid = menu.getPid();
Long newPid = args.getPid(); Long newPid = args.getPid();
if (StrUtil.isNotBlank(args.getComponentName())) { if (StrUtil.isNotBlank(args.getComponentName())) {
KitValidUtil.isTrue(this.existMenuWithComponentNameNeSelf(args.getTitle(), menu.getId()), "菜单组件名称已存在"); if (this.existMenuWithComponentNameNeSelf(args.getTitle(), menu.getId())) {
throw new BadRequestException("菜单组件名称已存在");
}
} }
menu.setTitle(args.getTitle()); menu.setTitle(args.getTitle());
menu.setComponent(args.getComponent()); menu.setComponent(args.getComponent());
@@ -137,7 +148,7 @@ public class SystemMenuService {
} }
/** /**
* 删除 * 删除 -> TestPassed
*/ */
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void deleteMenuByIds(Set<Long> ids) { public void deleteMenuByIds(Set<Long> ids) {
@@ -250,7 +261,7 @@ public class SystemMenuService {
} }
/** /**
* 根据ID查询同级与上级数据 * 根据ID查询同级与上级数据 -> TestPassed
* *
* @param menu / * @param menu /
* @param menus / * @param menus /
@@ -432,7 +443,7 @@ public class SystemMenuService {
} }
private List<SystemMenuTb> queryMenuByArgs(SystemQueryMenuArgs args) { private List<SystemMenuTb> queryMenuByArgs(SystemQueryMenuArgs args) {
KitValidUtil.isNull(args); KitValidUtil.notNull(args);
LambdaQueryWrapper<SystemMenuTb> wrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<SystemMenuTb> wrapper = new LambdaQueryWrapper<>();
wrapper.isNull(args.getPidIsNull() != null, SystemMenuTb::getPid); wrapper.isNull(args.getPidIsNull() != null, SystemMenuTb::getPid);
wrapper.eq(args.getPid() != null, SystemMenuTb::getPid, args.getPid()); wrapper.eq(args.getPid() != null, SystemMenuTb::getPid, args.getPid());
@@ -447,7 +458,7 @@ public class SystemMenuService {
} }
/** /**
* 查询根目录 * 查询根目录 -> TestPassed
*/ */
private List<SystemMenuTb> listRootMenu() { private List<SystemMenuTb> listRootMenu() {
LambdaQueryWrapper<SystemMenuTb> wrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<SystemMenuTb> wrapper = new LambdaQueryWrapper<>();
@@ -457,7 +468,7 @@ public class SystemMenuService {
} }
/** /**
* 根据组件名称查询菜单是否存在 * 根据组件名称查询菜单是否存在 -> TestPassed
* *
* @param componentName 组件名称 * @param componentName 组件名称
* @return / * @return /
@@ -469,7 +480,7 @@ public class SystemMenuService {
} }
/** /**
* 根据组件名称查询菜单是否存在 * 根据组件名称查询菜单是否存在 -> TestPassed
* *
* @param componentName 组件名称 * @param componentName 组件名称
* @return / * @return /
@@ -482,7 +493,7 @@ public class SystemMenuService {
} }
/** /**
* 根据菜单标题查询菜单是否存在 * 根据菜单标题查询菜单是否存在 -> TestPassed
* *
* @param title 菜单标题 * @param title 菜单标题
* @return / * @return /
@@ -494,7 +505,7 @@ public class SystemMenuService {
} }
/** /**
* 根据菜单标题查询菜单是否存在 * 根据菜单标题查询菜单是否存在 -> TestPassed
* *
* @param title 菜单标题 * @param title 菜单标题
* @return / * @return /
@@ -526,8 +537,7 @@ public class SystemMenuService {
List<SystemMenuTb> children = parentToChildrenMap.get(parentId); List<SystemMenuTb> children = parentToChildrenMap.get(parentId);
if (children != null && !children.isEmpty()) { if (children != null && !children.isEmpty()) {
for (SystemMenuTb child : children) { for (SystemMenuTb child : children) {
// 如果成功添加(之前不存在),则继续查找其子菜单 if (result.add(child.getId())) { // 如果成功添加(之前不存在),则继续查找其子菜单
if (result.add(child.getId())) {
nextLevelIds.add(child.getId()); nextLevelIds.add(child.getId());
} }
} }
@@ -553,7 +563,7 @@ public class SystemMenuService {
} }
/** /**
* 根据菜单id查询目录 * 根据菜单id查询目录 -> TestPassed
* *
* @param id 菜单id * @param id 菜单id
*/ */
@@ -47,7 +47,7 @@ public class SystemMonitorService {
private final DecimalFormat df = new DecimalFormat("0.00"); private final DecimalFormat df = new DecimalFormat("0.00");
/** /**
* 查询服务器监控信息 * 查询服务器监控信息 -> TestPassed
* *
* @return Map<String, Object> * @return Map<String, Object>
*/ */
@@ -75,7 +75,7 @@ public class SystemMonitorService {
} }
/** /**
* 查询磁盘信息 * 查询磁盘信息 -> TestPassed
* *
* @return / * @return /
*/ */
@@ -109,7 +109,7 @@ public class SystemMonitorService {
} }
/** /**
* 查询交换区信息 * 查询交换区信息 -> TestPassed
* *
* @param memory / * @param memory /
* @return / * @return /
@@ -131,7 +131,7 @@ public class SystemMonitorService {
} }
/** /**
* 查询内存信息 * 查询内存信息 -> TestPassed
* *
* @param memory / * @param memory /
* @return / * @return /
@@ -149,7 +149,7 @@ public class SystemMonitorService {
} }
/** /**
* 查询Cpu相关信息 * 查询Cpu相关信息 -> TestPassed
* *
* @param processor / * @param processor /
* @return / * @return /
@@ -196,7 +196,7 @@ public class SystemMonitorService {
} }
/** /**
* 查询系统相关信息,系统、运行天数、系统IP * 查询系统相关信息,系统、运行天数、系统IP -> TestPassed
* *
* @param os / * @param os /
* @return / * @return /
@@ -33,7 +33,7 @@ public class SystemOperationLogService {
private SystemOperationLogMapper systemOperationLogMapper; private SystemOperationLogMapper systemOperationLogMapper;
/** /**
* 查询用户操作日志 * 查询用户操作日志 -> TestPassed
*/ */
public IPage<SystemOperationLogTb> searchUserLog(KitPageArgs<SystemQueryOperationLogArgs> pageArgs) { public IPage<SystemOperationLogTb> searchUserLog(KitPageArgs<SystemQueryOperationLogArgs> pageArgs) {
LambdaQueryWrapper<SystemOperationLogTb> wrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<SystemOperationLogTb> wrapper = new LambdaQueryWrapper<>();
@@ -28,12 +28,12 @@ import cn.odboy.system.dal.model.export.SystemQuartzJobExportRowVo;
import cn.odboy.system.dal.model.export.SystemQuartzLogExportRowVo; import cn.odboy.system.dal.model.export.SystemQuartzLogExportRowVo;
import cn.odboy.system.dal.model.request.SystemQueryQuartzJobArgs; import cn.odboy.system.dal.model.request.SystemQueryQuartzJobArgs;
import cn.odboy.system.dal.model.request.SystemUpdateQuartzJobArgs; import cn.odboy.system.dal.model.request.SystemUpdateQuartzJobArgs;
import cn.odboy.system.dal.model.response.SystemQuartzJobVo;
import cn.odboy.system.dal.mysql.SystemQuartzJobMapper; import cn.odboy.system.dal.mysql.SystemQuartzJobMapper;
import cn.odboy.system.dal.mysql.SystemQuartzLogMapper; import cn.odboy.system.dal.mysql.SystemQuartzLogMapper;
import cn.odboy.system.framework.quartz.QuartzManage; import cn.odboy.system.framework.quartz.QuartzManage;
import cn.odboy.util.KitBeanUtil; import cn.odboy.util.KitBeanUtil;
import cn.odboy.util.KitPageUtil; import cn.odboy.util.KitPageUtil;
import cn.odboy.util.KitValidUtil;
import cn.odboy.util.xlsx.KitExcelExporter; import cn.odboy.util.xlsx.KitExcelExporter;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@@ -60,23 +60,27 @@ public class SystemQuartzJobService {
private KitRedisHelper redisHelper; private KitRedisHelper redisHelper;
/** /**
* 创建 * 创建 -> TestPassed
* *
* @param args / * @param args /
*/ */
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void createJob(SystemQuartzJobTb args) { public void createJob(SystemQuartzJobTb args) {
if (args.getId() != null) {
throw new BadRequestException("无效参数id");
}
// 验证Bean是不是合法的, 合法的定时任务 Bean 需要用 @Service 定义 // 验证Bean是不是合法的, 合法的定时任务 Bean 需要用 @Service 定义
checkBean(args.getBeanName()); checkBean(args.getBeanName());
if (!CronExpression.isValidExpression(args.getCronExpression())) { if (!CronExpression.isValidExpression(args.getCronExpression())) {
throw new BadRequestException("cron表达式格式错误"); throw new BadRequestException("cron表达式格式错误");
} }
systemQuartzJobMapper.insert(args); systemQuartzJobMapper.insert(args);
quartzManage.addJob(args); SystemQuartzJobVo quartzJobVo = KitBeanUtil.copyToClass(args, SystemQuartzJobVo.class);
quartzManage.addJob(quartzJobVo);
} }
/** /**
* 修改任务并重新调度 * 修改任务并重新调度 -> TestPassed
* *
* @param args / * @param args /
*/ */
@@ -84,10 +88,14 @@ public class SystemQuartzJobService {
public void updateQuartzJobResumeCron(SystemUpdateQuartzJobArgs args) { public void updateQuartzJobResumeCron(SystemUpdateQuartzJobArgs args) {
// 验证Bean是不是合法的, 合法的定时任务 Bean 需要用 @Service 定义 // 验证Bean是不是合法的, 合法的定时任务 Bean 需要用 @Service 定义
checkBean(args.getBeanName()); checkBean(args.getBeanName());
KitValidUtil.isTrue(!CronExpression.isValidExpression(args.getCronExpression()), "Cron表达式格式错误"); if (!CronExpression.isValidExpression(args.getCronExpression())) {
throw new BadRequestException("cron表达式格式错误");
}
if (StrUtil.isNotBlank(args.getSubTask())) { if (StrUtil.isNotBlank(args.getSubTask())) {
List<String> tasks = Arrays.asList(args.getSubTask().split("[,,]")); List<String> tasks = Arrays.asList(args.getSubTask().split("[,,]"));
KitValidUtil.isTrue(tasks.contains(args.getId().toString()), "子任务中不能添加当前任务ID"); if (tasks.contains(args.getId().toString())) {
throw new BadRequestException("子任务中不能添加当前任务ID");
}
} }
SystemQuartzJobTb jobTb = KitBeanUtil.copyToClass(args, SystemQuartzJobTb.class); SystemQuartzJobTb jobTb = KitBeanUtil.copyToClass(args, SystemQuartzJobTb.class);
systemQuartzJobMapper.updateById(jobTb); systemQuartzJobMapper.updateById(jobTb);
@@ -95,34 +103,35 @@ public class SystemQuartzJobService {
} }
/** /**
* 更改定时任务状态 * 更改定时任务状态 -> TestPassed
* *
* @param quartzJobTb / * @param quartzJobVo /
*/ */
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void switchQuartzJobStatus(SystemQuartzJobTb quartzJobTb) { public void switchQuartzJobStatus(SystemQuartzJobVo quartzJobVo) {
// 置换暂停状态 // 置换暂停状态
if (quartzJobTb.getIsPause()) { if (quartzJobVo.getIsPause()) {
quartzManage.resumeJob(quartzJobTb); quartzManage.resumeJob(quartzJobVo);
quartzJobTb.setIsPause(false); quartzJobVo.setIsPause(false);
} else { } else {
quartzManage.pauseJob(quartzJobTb); quartzManage.pauseJob(quartzJobVo);
quartzJobTb.setIsPause(true); quartzJobVo.setIsPause(true);
} }
systemQuartzJobMapper.updateById(quartzJobTb); SystemQuartzJobTb record = KitBeanUtil.copyToClass(quartzJobVo, SystemQuartzJobTb.class);
systemQuartzJobMapper.updateById(record);
} }
/** /**
* 立即执行定时任务 * 立即执行定时任务 -> TestPassed
* *
* @param quartzJob / * @param quartzJob /
*/ */
public void startQuartzJob(SystemQuartzJobTb quartzJob) { public void startQuartzJob(SystemQuartzJobVo quartzJob) {
quartzManage.runJobNow(quartzJob); quartzManage.runJobNow(quartzJob);
} }
/** /**
* 删除任务 * 删除任务 -> TestPassed
* *
* @param ids / * @param ids /
*/ */
@@ -136,7 +145,7 @@ public class SystemQuartzJobService {
} }
/** /**
* 执行子任务 * 执行子任务 -> TestPassed
* *
* @param tasks / * @param tasks /
* @throws InterruptedException / * @throws InterruptedException /
@@ -153,10 +162,11 @@ public class SystemQuartzJobService {
// 防止子任务不存在 // 防止子任务不存在
continue; continue;
} }
SystemQuartzJobVo quartzJobVo = KitBeanUtil.copyToClass(quartzJobTb, SystemQuartzJobVo.class);
// 执行任务 // 执行任务
String uuid = IdUtil.simpleUUID(); String uuid = IdUtil.simpleUUID();
quartzJobTb.setUuid(uuid); quartzJobVo.setUuid(uuid);
startQuartzJob(quartzJobTb); startQuartzJob(quartzJobVo);
// 查询执行状态, 如果执行失败则停止后面的子任务执行 // 查询执行状态, 如果执行失败则停止后面的子任务执行
Boolean result = redisHelper.get(uuid, Boolean.class); Boolean result = redisHelper.get(uuid, Boolean.class);
while (result == null) { while (result == null) {
@@ -172,7 +182,7 @@ public class SystemQuartzJobService {
} }
/** /**
* 分页查询 * 分页查询 -> TestPassed
* *
* @param args 条件 * @param args 条件
* @param page 分页参数 * @param page 分页参数
@@ -185,7 +195,7 @@ public class SystemQuartzJobService {
} }
/** /**
* 分页查询日志 * 分页查询日志 -> TestPassed
* *
* @param args 条件 * @param args 条件
* @param page 分页参数 * @param page 分页参数
@@ -198,7 +208,7 @@ public class SystemQuartzJobService {
} }
/** /**
* 查询全部 * 查询全部 -> TestPassed
* *
* @param args 条件 * @param args 条件
* @return / * @return /
@@ -210,7 +220,7 @@ public class SystemQuartzJobService {
} }
/** /**
* 查询全部 * 查询全部 -> TestPassed
* *
* @param args 条件 * @param args 条件
* @return / * @return /
@@ -222,7 +232,7 @@ public class SystemQuartzJobService {
} }
/** /**
* 查询启用的定时任务 * 查询启用的定时任务 -> TestPassed
*/ */
public List<SystemQuartzJobTb> listEnableQuartzJob() { public List<SystemQuartzJobTb> listEnableQuartzJob() {
LambdaQueryWrapper<SystemQuartzJobTb> wrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<SystemQuartzJobTb> wrapper = new LambdaQueryWrapper<>();
@@ -231,7 +241,7 @@ public class SystemQuartzJobService {
} }
/** /**
* 导出定时任务数据 * 导出定时任务数据 -> TestPassed
*/ */
public void exportQuartzJobXlsx(HttpServletResponse response, SystemQueryQuartzJobArgs args) { public void exportQuartzJobXlsx(HttpServletResponse response, SystemQueryQuartzJobArgs args) {
List<SystemQuartzJobTb> systemQuartzJobTbs = this.queryQuartzJobByArgs(args); List<SystemQuartzJobTb> systemQuartzJobTbs = this.queryQuartzJobByArgs(args);
@@ -252,7 +262,7 @@ public class SystemQuartzJobService {
} }
/** /**
* 导出定时任务日志数据 * 导出定时任务日志数据 -> TestPassed
*/ */
public void exportQuartzLogXlsx(HttpServletResponse response, SystemQueryQuartzJobArgs args) { public void exportQuartzLogXlsx(HttpServletResponse response, SystemQueryQuartzJobArgs args) {
List<SystemQuartzLogTb> systemQuartzLogTbs = this.queryQuartzLogByArgs(args); List<SystemQuartzLogTb> systemQuartzLogTbs = this.queryQuartzLogByArgs(args);
@@ -274,7 +284,7 @@ public class SystemQuartzJobService {
} }
/** /**
* 根据任务id查询定时任务 * 根据任务id查询定时任务 -> TestPassed
*/ */
public SystemQuartzJobTb getQuartzJobById(Long id) { public SystemQuartzJobTb getQuartzJobById(Long id) {
return systemQuartzJobMapper.selectById(id); return systemQuartzJobMapper.selectById(id);
@@ -322,7 +332,9 @@ public class SystemQuartzJobService {
*/ */
private void checkBean(String beanName) { private void checkBean(String beanName) {
// 避免调用攻击者可以从SpringContextHolder获得控制jdbcTemplate类 // 避免调用攻击者可以从SpringContextHolder获得控制jdbcTemplate类
// 并使用getDeclaredMethod调用jdbcTemplate的queryForMap函数,执行任意sql命令 // 并使用getDeclaredMethod调用jdbcTemplate的queryForMap函数,执行任意sql命令。
KitValidUtil.isTrue(!KitSpringBeanHolder.getAllServiceBeanName().contains(beanName), "非法的 Bean,请重新输入"); if (!KitSpringBeanHolder.getAllServiceBeanName().contains(beanName)) {
throw new BadRequestException("非法的 Bean,请重新输入!");
}
} }
} }
@@ -34,7 +34,7 @@ public class SystemRoleDeptService {
private SystemRoleDeptMapper systemRoleDeptMapper; private SystemRoleDeptMapper systemRoleDeptMapper;
/** /**
* 批量删除角色部门关联 * 批量删除角色部门关联 -> TestPassed
* *
* @param roleIds 角色id集合 * @param roleIds 角色id集合
*/ */
@@ -48,7 +48,7 @@ public class SystemRoleDeptService {
} }
/** /**
* 批量绑定角色部门关联 * 批量绑定角色部门关联 -> TestPassed
* *
* @param depts 部门集合 * @param depts 部门集合
* @param roleId 角色id * @param roleId 角色id
@@ -68,7 +68,7 @@ public class SystemRoleDeptService {
} }
/** /**
* 根据部门ID统计角色数量 * 根据部门ID统计角色数量 -> TestPassed
* *
* @param deptIds 部门id集合 * @param deptIds 部门id集合
* @return / * @return /
@@ -83,7 +83,7 @@ public class SystemRoleDeptService {
} }
/** /**
* 根据角色id查询部门信息 * 根据角色id查询部门信息 -> TestPassed
* *
* @param roleId 角色id * @param roleId 角色id
* @return / * @return /
@@ -36,7 +36,7 @@ public class SystemRoleMenuService {
private SystemRoleMenuMapper systemRoleMenuMapper; private SystemRoleMenuMapper systemRoleMenuMapper;
/** /**
* 删除角色菜单关联 * 删除角色菜单关联 -> TestPassed
* *
* @param roleId 角色id * @param roleId 角色id
*/ */
@@ -48,7 +48,7 @@ public class SystemRoleMenuService {
} }
/** /**
* 批量绑定角色菜单关联 * 批量绑定角色菜单关联 -> TestPassed
* *
* @param menus 菜单集合 * @param menus 菜单集合
* @param roleId 角色id * @param roleId 角色id
@@ -68,7 +68,7 @@ public class SystemRoleMenuService {
} }
/** /**
* 批量删除角色菜单关联 * 批量删除角色菜单关联 -> TestPassed
* *
* @param roleIds 角色id集合 * @param roleIds 角色id集合
*/ */
@@ -82,7 +82,7 @@ public class SystemRoleMenuService {
} }
/** /**
* @param roleIds 角色id集合 * @param roleIds 角色id集合 -> TestPassed
* @return / * @return /
*/ */
public List<SystemMenuTb> listMenuByRoleIds(Set<Long> roleIds, boolean hasButton) { public List<SystemMenuTb> listMenuByRoleIds(Set<Long> roleIds, boolean hasButton) {
@@ -109,7 +109,7 @@ public class SystemRoleMenuService {
} }
/** /**
* 批量删除菜单角色关联 * 批量删除菜单角色关联 -> TestPassed
* *
* @param menuIds 菜单id集合 * @param menuIds 菜单id集合
*/ */
@@ -124,7 +124,7 @@ public class SystemRoleMenuService {
} }
/** /**
* 根据角色id集合查询菜单权限 * 根据角色id集合查询菜单权限 -> TestPassed
* *
* @param roleIds 角色id集合 * @param roleIds 角色id集合
* @return / * @return /
@@ -19,6 +19,7 @@ import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Dict; import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import cn.odboy.base.KitPageResult; import cn.odboy.base.KitPageResult;
import cn.odboy.framework.exception.BadRequestException;
import cn.odboy.system.dal.dataobject.SystemMenuTb; import cn.odboy.system.dal.dataobject.SystemMenuTb;
import cn.odboy.system.dal.dataobject.SystemRoleTb; import cn.odboy.system.dal.dataobject.SystemRoleTb;
import cn.odboy.system.dal.model.export.SystemRoleExportRowVo; import cn.odboy.system.dal.model.export.SystemRoleExportRowVo;
@@ -31,7 +32,6 @@ import cn.odboy.system.dal.mysql.SystemRoleMapper;
import cn.odboy.system.framework.permission.core.KitSecurityHelper; import cn.odboy.system.framework.permission.core.KitSecurityHelper;
import cn.odboy.util.KitBeanUtil; import cn.odboy.util.KitBeanUtil;
import cn.odboy.util.KitPageUtil; import cn.odboy.util.KitPageUtil;
import cn.odboy.util.KitValidUtil;
import cn.odboy.util.xlsx.KitExcelExporter; import cn.odboy.util.xlsx.KitExcelExporter;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage;
@@ -60,14 +60,16 @@ public class SystemRoleService {
private SystemUserRoleService systemUserRoleService; private SystemUserRoleService systemUserRoleService;
/** /**
* 创建 * 创建 -> TestPassed
* *
* @param args / * @param args /
*/ */
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void saveRole(SystemCreateRoleArgs args) { public void saveRole(SystemCreateRoleArgs args) {
this.checkRoleLevels(args.getLevel()); this.checkRoleLevels(args.getLevel());
KitValidUtil.isTrue(this.existRoleWithName(args.getName()), "角色名称已存在"); if (this.existRoleWithName(args.getName())) {
throw new BadRequestException("角色名称已存在");
}
SystemRoleTb roleTb = KitBeanUtil.copyToClass(args, SystemRoleTb.class); SystemRoleTb roleTb = KitBeanUtil.copyToClass(args, SystemRoleTb.class);
systemRoleMapper.insert(roleTb); systemRoleMapper.insert(roleTb);
// 判断是否有部门数据, 若有, 则需创建关联 // 判断是否有部门数据, 若有, 则需创建关联
@@ -77,7 +79,7 @@ public class SystemRoleService {
} }
/** /**
* 修改 * 修改 -> TestPassed
* *
* @param args / * @param args /
*/ */
@@ -85,7 +87,9 @@ public class SystemRoleService {
public void updateRoleById(SystemRoleVo args) { public void updateRoleById(SystemRoleVo args) {
this.checkRoleLevels(args.getLevel()); this.checkRoleLevels(args.getLevel());
SystemRoleTb role = systemRoleMapper.selectById(args.getId()); SystemRoleTb role = systemRoleMapper.selectById(args.getId());
KitValidUtil.isTrue(this.existRoleWithNameNeSelf(args.getName(), role.getId()), "角色名称已存在"); if (this.existRoleWithNameNeSelf(args.getName(), role.getId())) {
throw new BadRequestException("角色名称已存在");
}
role.setName(args.getName()); role.setName(args.getName());
role.setDescription(args.getDescription()); role.setDescription(args.getDescription());
role.setDataScope(args.getDataScope()); role.setDataScope(args.getDataScope());
@@ -101,7 +105,7 @@ public class SystemRoleService {
} }
/** /**
* 修改绑定的菜单 * 修改绑定的菜单 -> TestPassed
* *
* @param args / * @param args /
*/ */
@@ -118,7 +122,7 @@ public class SystemRoleService {
} }
/** /**
* 删除 * 删除 -> TestPassed
* *
* @param ids / * @param ids /
*/ */
@@ -129,7 +133,7 @@ public class SystemRoleService {
this.checkRoleLevels(roleLevel); this.checkRoleLevels(roleLevel);
} }
// 验证是否被用户关联 // 验证是否被用户关联
KitValidUtil.isTrue(systemUserRoleService.existUserWithRoleIds(ids), "所选角色存在用户关联, 请解除关联再试"); this.verifyBindRelationByIds(ids);
// 删除角色 // 删除角色
systemRoleMapper.deleteByIds(ids); systemRoleMapper.deleteByIds(ids);
// 删除角色部门关联数据、角色菜单关联数据 // 删除角色部门关联数据、角色菜单关联数据
@@ -138,7 +142,7 @@ public class SystemRoleService {
} }
/** /**
* 查询全部角色 * 查询全部角色 -> TestPassed
*/ */
public List<SystemRoleTb> listAllRole() { public List<SystemRoleTb> listAllRole() {
LambdaQueryWrapper<SystemRoleTb> wrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<SystemRoleTb> wrapper = new LambdaQueryWrapper<>();
@@ -147,7 +151,7 @@ public class SystemRoleService {
} }
/** /**
* 根据条件查询全部角色 * 根据条件查询全部角色 -> TestPassed
* *
* @param args 条件 * @param args 条件
* @param rolePage 分页参数 * @param rolePage 分页参数
@@ -160,7 +164,7 @@ public class SystemRoleService {
} }
/** /**
* 分页查询角色 * 分页查询角色 -> TestPassed
* *
* @param args 条件 * @param args 条件
* @param page 分页条件 * @param page 分页条件
@@ -174,7 +178,7 @@ public class SystemRoleService {
} }
/** /**
* 查询用户权限信息? * 查询用户权限信息 -> TestPassed?
* *
* @param user 用户信息 * @param user 用户信息
* @return 权限信息 * @return 权限信息
@@ -200,6 +204,17 @@ public class SystemRoleService {
return permissions.stream().map(SystemRoleCodeVo::new).collect(Collectors.toList()); return permissions.stream().map(SystemRoleCodeVo::new).collect(Collectors.toList());
} }
/**
* 验证是否被用户关联 -> TestPassed
*
* @param ids /
*/
public void verifyBindRelationByIds(Set<Long> ids) {
if (systemUserRoleService.existUserWithRoleIds(ids)) {
throw new BadRequestException("所选角色存在用户关联, 请解除关联再试!");
}
}
/** /**
* 根据角色id查询用户可访问的部门和菜单信息 * 根据角色id查询用户可访问的部门和菜单信息
* *
@@ -266,7 +281,7 @@ public class SystemRoleService {
} }
/** /**
* 检查用户的角色级别 * 检查用户的角色级别 -> TestPassed
* *
* @return / * @return /
*/ */
@@ -274,7 +289,9 @@ public class SystemRoleService {
Set<Integer> levels = systemUserRoleService.listUserRoleLevelByUserId(KitSecurityHelper.getCurrentUserId()); Set<Integer> levels = systemUserRoleService.listUserRoleLevelByUserId(KitSecurityHelper.getCurrentUserId());
int min = Collections.min(levels); int min = Collections.min(levels);
if (level != null) { if (level != null) {
KitValidUtil.isTrue(level < min, "权限不足, 你的角色级别:" + min + ", 低于操作的角色级别:" + level); if (level < min) {
throw new BadRequestException("权限不足, 你的角色级别:" + min + ", 低于操作的角色级别:" + level);
}
} }
return min; return min;
} }

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