diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java index 64e219830..6c8d22019 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java @@ -2,7 +2,6 @@ package com.ruoyi.web.controller.system; import com.ruoyi.common.annotation.Log; import com.ruoyi.common.constant.UserConstants; -import com.ruoyi.common.core.controller.BaseController; import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.enums.BusinessType; @@ -13,6 +12,7 @@ import com.ruoyi.system.domain.SysUser; import com.ruoyi.system.domain.SysUserRole; import com.ruoyi.system.service.ISysRoleService; import com.ruoyi.system.service.ISysUserService; +import com.ruoyi.web.controller.system.base.WebController; import org.apache.shiro.authz.annotation.RequiresPermissions; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Pageable; @@ -30,7 +30,7 @@ import java.util.List; */ @Controller @RequestMapping("/system/role") -public class SysRoleController extends BaseController { +public class SysRoleController extends WebController { private String prefix = "system/role"; @Autowired @@ -49,7 +49,7 @@ public class SysRoleController extends BaseController { @PostMapping("/list") @ResponseBody public TableDataInfo list(SysRole role) { - return getDataTable(roleService.selectRoleList(role, getPageRequest())); + return getDataTable(roleService.selectRoleList(role, getPageRequest(), getUser())); } @Log(title = "角色管理", businessType = BusinessType.EXPORT) @@ -57,7 +57,7 @@ public class SysRoleController extends BaseController { @PostMapping("/export") @ResponseBody public AjaxResult export(SysRole role) { - List list = roleService.selectRoleList(role, Pageable.unpaged()).getContent(); + List list = roleService.selectRoleList(role, Pageable.unpaged(), getUser()).getContent(); ExcelUtil util = new ExcelUtil(SysRole.class); return util.exportExcel(list, "角色数据"); } diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/base/WebController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/base/WebController.java new file mode 100644 index 000000000..24e5119fa --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/base/WebController.java @@ -0,0 +1,12 @@ +package com.ruoyi.web.controller.system.base; + +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.framework.util.ShiroUtils; +import com.ruoyi.system.domain.SysUser; + +public class WebController extends BaseController { + + protected SysUser getUser(){ + return ShiroUtils.getSysUser(); + } +} diff --git a/ruoyi-admin/src/main/resources/application-druid.yml b/ruoyi-admin/src/main/resources/application-druid.yml index b848b4f9e..e865580dd 100644 --- a/ruoyi-admin/src/main/resources/application-druid.yml +++ b/ruoyi-admin/src/main/resources/application-druid.yml @@ -68,7 +68,7 @@ spring: url: jdbc:mysql://localhost:3306/mysql?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 user: ${db.username} password: ${db.password} - #需要目标数据库已经存在,不自动升级 + #目标数据库已经存在,不自动升级 baseline-on-migrate: false encoding: utf-8 clean-on-validation-error: false diff --git a/ruoyi-admin/src/main/resources/static/ruoyi/index.js b/ruoyi-admin/src/main/resources/static/ruoyi/index.js index 2e130d377..f346c6c38 100644 --- a/ruoyi-admin/src/main/resources/static/ruoyi/index.js +++ b/ruoyi-admin/src/main/resources/static/ruoyi/index.js @@ -1,594 +1,602 @@ -/** - * 首页方法封装处理 - * Copyright (c) 2019 ruoyi - */ -layer.config({ - extend: 'moon/style.css', - skin: 'layer-ext-moon' -}); - -$(function() { - // MetsiMenu - $('#side-menu').metisMenu(); - - //固定菜单栏 - $(function() { - $('.sidebar-collapse').slimScroll({ - height: '100%', - railOpacity: 0.9, - alwaysVisible: false - }); - }); - - // 菜单切换 - $('.navbar-minimalize').click(function() { - $("body").toggleClass("mini-navbar"); - SmoothlyMenu(); - }); - - $('#side-menu>li').click(function() { - if ($('body').hasClass('mini-navbar')) { - NavToggle(); - } - }); - $('#side-menu>li li a').click(function() { - if ($(window).width() < 769) { - NavToggle(); - } - }); - - $('.nav-close').click(NavToggle); - - //ios浏览器兼容性处理 - if (/(iPhone|iPad|iPod|iOS)/i.test(navigator.userAgent)) { - $('#content-main').css('overflow-y', 'auto'); - } - -}); - -$(window).bind("load resize", -function() { - if ($(this).width() < 769) { - $('body').addClass('mini-navbar'); - $('.navbar-static-side').fadeIn(); - $(".sidebar-collapse .logo").addClass("hide"); - $(".slimScrollDiv").css({ "overflow":"hidden" }) - } -}); - -function NavToggle() { - $('.navbar-minimalize').trigger('click'); -} - -function SmoothlyMenu() { - if (!$('body').hasClass('mini-navbar')) { - $('#side-menu').hide(); - $(".sidebar-collapse .logo").removeClass("hide"); - setTimeout(function() { - $('#side-menu').fadeIn(500); - }, - 100); - } else if ($('body').hasClass('fixed-sidebar')) { - $('#side-menu').hide(); - $(".sidebar-collapse .logo").addClass("hide"); - setTimeout(function() { - $('#side-menu').fadeIn(500); - }, - 300); - } else { - $('#side-menu').removeAttr('style'); - } -} - -/** - * iframe处理 - */ -$(function() { - //计算元素集合的总宽度 - function calSumWidth(elements) { - var width = 0; - $(elements).each(function() { - width += $(this).outerWidth(true); - }); - return width; - } - - // 激活指定选项卡 - function setActiveTab(element) { - if (!$(element).hasClass('active')) { - var currentId = $(element).data('id'); - // 显示tab对应的内容区 - $('.RuoYi_iframe').each(function() { - if ($(this).data('id') == currentId) { - $(this).show().siblings('.RuoYi_iframe').hide(); - } - }); - $(element).addClass('active').siblings('.menuTab').removeClass('active'); - scrollToTab(element); - } - } - - //滚动到指定选项卡 - function scrollToTab(element) { - var marginLeftVal = calSumWidth($(element).prevAll()), - marginRightVal = calSumWidth($(element).nextAll()); - // 可视区域非tab宽度 - var tabOuterWidth = calSumWidth($(".content-tabs").children().not(".menuTabs")); - //可视区域tab宽度 - var visibleWidth = $(".content-tabs").outerWidth(true) - tabOuterWidth; - //实际滚动宽度 - var scrollVal = 0; - if ($(".page-tabs-content").outerWidth() < visibleWidth) { - scrollVal = 0; - } else if (marginRightVal <= (visibleWidth - $(element).outerWidth(true) - $(element).next().outerWidth(true))) { - if ((visibleWidth - $(element).next().outerWidth(true)) > marginRightVal) { - scrollVal = marginLeftVal; - var tabElement = element; - while ((scrollVal - $(tabElement).outerWidth()) > ($(".page-tabs-content").outerWidth() - visibleWidth)) { - scrollVal -= $(tabElement).prev().outerWidth(); - tabElement = $(tabElement).prev(); - } - } - } else if (marginLeftVal > (visibleWidth - $(element).outerWidth(true) - $(element).prev().outerWidth(true))) { - scrollVal = marginLeftVal - $(element).prev().outerWidth(true); - } - $('.page-tabs-content').animate({ - marginLeft: 0 - scrollVal + 'px' - }, - "fast"); - } - - //查看左侧隐藏的选项卡 - function scrollTabLeft() { - var marginLeftVal = Math.abs(parseInt($('.page-tabs-content').css('margin-left'))); - // 可视区域非tab宽度 - var tabOuterWidth = calSumWidth($(".content-tabs").children().not(".menuTabs")); - //可视区域tab宽度 - var visibleWidth = $(".content-tabs").outerWidth(true) - tabOuterWidth; - //实际滚动宽度 - var scrollVal = 0; - if (($(".page-tabs-content").width()) < visibleWidth) { - return false; - } else { - var tabElement = $(".menuTab:first"); - var offsetVal = 0; - while ((offsetVal + $(tabElement).outerWidth(true)) <= marginLeftVal) { //找到离当前tab最近的元素 - offsetVal += $(tabElement).outerWidth(true); - tabElement = $(tabElement).next(); - } - offsetVal = 0; - if (calSumWidth($(tabElement).prevAll()) > visibleWidth) { - while ((offsetVal + $(tabElement).outerWidth(true)) < (visibleWidth) && tabElement.length > 0) { - offsetVal += $(tabElement).outerWidth(true); - tabElement = $(tabElement).prev(); - } - scrollVal = calSumWidth($(tabElement).prevAll()); - } - } - $('.page-tabs-content').animate({ - marginLeft: 0 - scrollVal + 'px' - }, - "fast"); - } - - //查看右侧隐藏的选项卡 - function scrollTabRight() { - var marginLeftVal = Math.abs(parseInt($('.page-tabs-content').css('margin-left'))); - // 可视区域非tab宽度 - var tabOuterWidth = calSumWidth($(".content-tabs").children().not(".menuTabs")); - //可视区域tab宽度 - var visibleWidth = $(".content-tabs").outerWidth(true) - tabOuterWidth; - //实际滚动宽度 - var scrollVal = 0; - if ($(".page-tabs-content").width() < visibleWidth) { - return false; - } else { - var tabElement = $(".menuTab:first"); - var offsetVal = 0; - while ((offsetVal + $(tabElement).outerWidth(true)) <= marginLeftVal) { //找到离当前tab最近的元素 - offsetVal += $(tabElement).outerWidth(true); - tabElement = $(tabElement).next(); - } - offsetVal = 0; - while ((offsetVal + $(tabElement).outerWidth(true)) < (visibleWidth) && tabElement.length > 0) { - offsetVal += $(tabElement).outerWidth(true); - tabElement = $(tabElement).next(); - } - scrollVal = calSumWidth($(tabElement).prevAll()); - if (scrollVal > 0) { - $('.page-tabs-content').animate({ - marginLeft: 0 - scrollVal + 'px' - }, - "fast"); - } - } - } - - //通过遍历给菜单项加上data-index属性 - $(".menuItem").each(function(index) { - if (!$(this).attr('data-index')) { - $(this).attr('data-index', index); - } - }); - - function menuItem() { - // 获取标识数据 - var dataUrl = $(this).attr('href'), - dataIndex = $(this).data('index'), - menuName = $.trim($(this).text()), - flag = true; - $(".nav ul li, .nav li").removeClass("selected"); - $(this).parent("li").addClass("selected"); - setIframeUrl($(this).attr("href")); - if (dataUrl == undefined || $.trim(dataUrl).length == 0) return false; - - // 选项卡菜单已存在 - $('.menuTab').each(function() { - if ($(this).data('id') == dataUrl) { - if (!$(this).hasClass('active')) { - $(this).addClass('active').siblings('.menuTab').removeClass('active'); - scrollToTab(this); - // 显示tab对应的内容区 - $('.mainContent .RuoYi_iframe').each(function() { - if ($(this).data('id') == dataUrl) { - $(this).show().siblings('.RuoYi_iframe').hide(); - return false; - } - }); - } - flag = false; - return false; - } - }); - // 选项卡菜单不存在 - if (flag) { - var str = '' + menuName + ' '; - $('.menuTab').removeClass('active'); - - // 添加选项卡对应的iframe - var str1 = ''; - $('.mainContent').find('iframe.RuoYi_iframe').hide().parents('.mainContent').append(str1); - - $.modal.loading("数据加载中,请稍后..."); - - $('.mainContent iframe:visible').load(function () { - $.modal.closeLoading(); - }); - - // 添加选项卡 - $('.menuTabs .page-tabs-content').append(str); - scrollToTab($('.menuTab.active')); - } - return false; - } - - function menuBlank() { - // 新窗口打开外网以http://开头,如http://ruoyi.vip - var dataUrl = $(this).attr('href'); - window.open(dataUrl); - return false; - } - - $('.menuItem').on('click', menuItem); - - $('.menuBlank').on('click', menuBlank); - - // 关闭选项卡菜单 - function closeTab() { - var closeTabId = $(this).parents('.menuTab').data('id'); - var currentWidth = $(this).parents('.menuTab').width(); - var panelUrl = $(this).parents('.menuTab').data('panel'); - // 当前元素处于活动状态 - if ($(this).parents('.menuTab').hasClass('active')) { - - // 当前元素后面有同辈元素,使后面的一个元素处于活动状态 - if ($(this).parents('.menuTab').next('.menuTab').size()) { - - var activeId = $(this).parents('.menuTab').next('.menuTab:eq(0)').data('id'); - $(this).parents('.menuTab').next('.menuTab:eq(0)').addClass('active'); - - $('.mainContent .RuoYi_iframe').each(function() { - if ($(this).data('id') == activeId) { - $(this).show().siblings('.RuoYi_iframe').hide(); - return false; - } - }); - - var marginLeftVal = parseInt($('.page-tabs-content').css('margin-left')); - if (marginLeftVal < 0) { - $('.page-tabs-content').animate({ - marginLeft: (marginLeftVal + currentWidth) + 'px' - }, - "fast"); - } - - // 移除当前选项卡 - $(this).parents('.menuTab').remove(); - - // 移除tab对应的内容区 - $('.mainContent .RuoYi_iframe').each(function() { - if ($(this).data('id') == closeTabId) { - $(this).remove(); - return false; - } - }); - } - - // 当前元素后面没有同辈元素,使当前元素的上一个元素处于活动状态 - if ($(this).parents('.menuTab').prev('.menuTab').size()) { - var activeId = $(this).parents('.menuTab').prev('.menuTab:last').data('id'); - $(this).parents('.menuTab').prev('.menuTab:last').addClass('active'); - $('.mainContent .RuoYi_iframe').each(function() { - if ($(this).data('id') == activeId) { - $(this).show().siblings('.RuoYi_iframe').hide(); - return false; - } - }); - - // 移除当前选项卡 - $(this).parents('.menuTab').remove(); - - // 移除tab对应的内容区 - $('.mainContent .RuoYi_iframe').each(function() { - if ($(this).data('id') == closeTabId) { - $(this).remove(); - return false; - } - }); - - if($.common.isNotEmpty(panelUrl)){ - $('.menuTab[data-id="' + panelUrl + '"]').addClass('active').siblings('.menuTab').removeClass('active'); - $('.mainContent .RuoYi_iframe').each(function() { - if ($(this).data('id') == panelUrl) { - $(this).show().siblings('.RuoYi_iframe').hide(); - return false; - } - }); - } - } - } - // 当前元素不处于活动状态 - else { - // 移除当前选项卡 - $(this).parents('.menuTab').remove(); - - // 移除相应tab对应的内容区 - $('.mainContent .RuoYi_iframe').each(function() { - if ($(this).data('id') == closeTabId) { - $(this).remove(); - return false; - } - }); - } - scrollToTab($('.menuTab.active')); - return false; - } - - $('.menuTabs').on('click', '.menuTab i', closeTab); - - //滚动到已激活的选项卡 - function showActiveTab() { - scrollToTab($('.menuTab.active')); - } - $('.tabShowActive').on('click', showActiveTab); - - // 点击选项卡菜单 - function activeTab() { - if (!$(this).hasClass('active')) { - var currentId = $(this).data('id'); - // 显示tab对应的内容区 - $('.mainContent .RuoYi_iframe').each(function() { - if ($(this).data('id') == currentId) { - $(this).show().siblings('.RuoYi_iframe').hide(); - return false; - } - }); - $(this).addClass('active').siblings('.menuTab').removeClass('active'); - scrollToTab(this); - } - } - - // 点击选项卡菜单 - $('.menuTabs').on('click', '.menuTab', activeTab); - - // 刷新iframe - function refreshTab() { - var currentId = $('.page-tabs-content').find('.active').attr('data-id'); - var target = $('.RuoYi_iframe[data-id="' + currentId + '"]'); - var url = target.attr('src'); - target.attr('src', url).ready(); - } - - // 页签全屏 - function fullScreenTab() { - var currentId = $('.page-tabs-content').find('.active').attr('data-id'); - var target = $('.RuoYi_iframe[data-id="' + currentId + '"]'); - target.fullScreen(true); - } - - // 关闭当前选项卡 - function tabCloseCurrent() { - $('.page-tabs-content').find('.active i').trigger("click"); - } - - //关闭其他选项卡 - function tabCloseOther() { - $('.page-tabs-content').children("[data-id]").not(":first").not(".active").each(function() { - $('.RuoYi_iframe[data-id="' + $(this).data('id') + '"]').remove(); - $(this).remove(); - }); - $('.page-tabs-content').css("margin-left", "0"); - } - - // 关闭全部选项卡 - function tabCloseAll() { - $('.page-tabs-content').children("[data-id]").not(":first").each(function() { - $('.RuoYi_iframe[data-id="' + $(this).data('id') + '"]').remove(); - $(this).remove(); - }); - $('.page-tabs-content').children("[data-id]:first").each(function() { - $('.RuoYi_iframe[data-id="' + $(this).data('id') + '"]').show(); - $(this).addClass("active"); - }); - $('.page-tabs-content').css("margin-left", "0"); - } - - - // 全屏显示 - $('#fullScreen').on('click', function () { - $(document).toggleFullScreen(); - }); - - // 页签刷新按钮 - $('.tabReload').on('click', refreshTab); - - // 页签全屏按钮 - $('.tabFullScreen').on('click', fullScreenTab); - - // 双击选项卡全屏显示 - $('.menuTabs').on('dblclick', '.menuTab', activeTabMax); - - // 左移按扭 - $('.tabLeft').on('click', scrollTabLeft); - - // 右移按扭 - $('.tabRight').on('click', scrollTabRight); - - // 关闭当前 - $('.tabCloseCurrent').on('click', tabCloseCurrent); - - // 关闭其他 - $('.tabCloseOther').on('click', tabCloseOther); - - // 关闭全部 - $('.tabCloseAll').on('click', tabCloseAll); - - // tab全屏显示 - $('.tabMaxCurrent').on('click', function () { - $('.page-tabs-content').find('.active').trigger("dblclick"); - }); - - // 关闭全屏 - $('#ax_close_max').click(function(){ - $('#content-main').toggleClass('max'); - $('#ax_close_max').hide(); - }) - - // 双击选项卡全屏显示 - function activeTabMax() { - $('#content-main').toggleClass('max'); - $('#ax_close_max').show(); - } - - // 设置锚点 - function setIframeUrl(href) { - if($.common.equals("history", mode)) { - storage.set('publicPath', href); - } else { - var nowUrl = window.location.href; - var newUrl = nowUrl.substring(0, nowUrl.indexOf("#")); - window.location.href = newUrl + "#" + href; - } - } - - $(window).keydown(function(event) { - if (event.keyCode == 27) { - $('#content-main').removeClass('max'); - $('#ax_close_max').hide(); - } - }); - - window.onhashchange = function() { - var hash = location.hash; - var url = hash.substring(1, hash.length); - $('a[href$="' + url + '"]').click(); - }; - - // 右键菜单实现 - $.contextMenu({ - selector: ".menuTab", - trigger: 'right', - autoHide: true, - items: { - "close_current": { - name: "关闭当前", - icon: "fa-close", - callback: function(key, opt) { - opt.$trigger.find('i').trigger("click"); - } - }, - "close_other": { - name: "关闭其他", - icon: "fa-window-close-o", - callback: function(key, opt) { - setActiveTab(this); - tabCloseOther(); - } - }, - "close_left": { - name: "关闭左侧", - icon: "fa-reply", - callback: function(key, opt) { - setActiveTab(this); - this.prevAll('.menuTab').not(":last").each(function() { - if ($(this).hasClass('active')) { - setActiveTab(this); - } - $('.RuoYi_iframe[data-id="' + $(this).data('id') + '"]').remove(); - $(this).remove(); - }); - $('.page-tabs-content').css("margin-left", "0"); - } - }, - "close_right": { - name: "关闭右侧", - icon: "fa-share", - callback: function(key, opt) { - setActiveTab(this); - this.nextAll('.menuTab').each(function() { - $('.menuTab[data-id="' + $(this).data('id') + '"]').remove(); - $(this).remove(); - }); - } - }, - "close_all": { - name: "全部关闭", - icon: "fa-window-close", - callback: function(key, opt) { - tabCloseAll(); - } - }, - "step": "---------", - "full": { - name: "全屏显示", - icon: "fa-arrows-alt", - callback: function(key, opt) { - setActiveTab(this); - var target = $('.RuoYi_iframe[data-id="' + this.data('id') + '"]'); - target.fullScreen(true); - } - }, - "refresh": { - name: "刷新页面", - icon: "fa-refresh", - callback: function(key, opt) { - setActiveTab(this); - var target = $('.RuoYi_iframe[data-id="' + this.data('id') + '"]'); - var url = target.attr('src'); - $.modal.loading("数据加载中,请稍后..."); - target.attr('src', url).load(function () { - $.modal.closeLoading(); - }); - } - }, - "open": { - name: "新窗口打开", - icon: "fa-link", - callback: function(key, opt) { - var target = $('.RuoYi_iframe[data-id="' + this.data('id') + '"]'); - window.open(target.attr('src')); - } - }, - } - }) +/** + * 首页方法封装处理 + * Copyright (c) 2019 ruoyi + */ +layer.config({ + extend: 'moon/style.css', + skin: 'layer-ext-moon' +}); + +var currentMenuId = null; + +$(function() { + // MetsiMenu + $('#side-menu').metisMenu(); + + //固定菜单栏 + $(function() { + $('.sidebar-collapse').slimScroll({ + height: '100%', + railOpacity: 0.9, + alwaysVisible: false + }); + }); + + // 菜单切换 + $('.navbar-minimalize').click(function() { + $("body").toggleClass("mini-navbar"); + SmoothlyMenu(); + }); + + $('#side-menu>li').click(function() { + if ($('body').hasClass('mini-navbar')) { + NavToggle(); + } + }); + $('#side-menu>li li a').click(function() { + if ($(window).width() < 769) { + NavToggle(); + } + }); + + $('.nav-close').click(NavToggle); + + //ios浏览器兼容性处理 + if (/(iPhone|iPad|iPod|iOS)/i.test(navigator.userAgent)) { + $('#content-main').css('overflow-y', 'auto'); + } + +}); + +$(window).bind("load resize", +function() { + if ($(this).width() < 769) { + $('body').addClass('mini-navbar'); + $('.navbar-static-side').fadeIn(); + $(".sidebar-collapse .logo").addClass("hide"); + $(".slimScrollDiv").css({ "overflow":"hidden" }) + } +}); + +function NavToggle() { + $('.navbar-minimalize').trigger('click'); +} + +function SmoothlyMenu() { + if (!$('body').hasClass('mini-navbar')) { + $('#side-menu').hide(); + $(".sidebar-collapse .logo").removeClass("hide"); + setTimeout(function() { + $('#side-menu').fadeIn(500); + }, + 100); + } else if ($('body').hasClass('fixed-sidebar')) { + $('#side-menu').hide(); + $(".sidebar-collapse .logo").addClass("hide"); + setTimeout(function() { + $('#side-menu').fadeIn(500); + }, + 300); + } else { + $('#side-menu').removeAttr('style'); + } +} + +/** + * iframe处理 + */ +$(function() { + //计算元素集合的总宽度 + function calSumWidth(elements) { + var width = 0; + $(elements).each(function() { + width += $(this).outerWidth(true); + }); + return width; + } + + // 激活指定选项卡 + function setActiveTab(element) { + if (!$(element).hasClass('active')) { + var currentId = $(element).data('id'); + // 显示tab对应的内容区 + $('.RuoYi_iframe').each(function() { + if ($(this).data('id') == currentId) { + $(this).show().siblings('.RuoYi_iframe').hide(); + } + }); + $(element).addClass('active').siblings('.menuTab').removeClass('active'); + scrollToTab(element); + } + } + + //滚动到指定选项卡 + function scrollToTab(element) { + var marginLeftVal = calSumWidth($(element).prevAll()), + marginRightVal = calSumWidth($(element).nextAll()); + // 可视区域非tab宽度 + var tabOuterWidth = calSumWidth($(".content-tabs").children().not(".menuTabs")); + //可视区域tab宽度 + var visibleWidth = $(".content-tabs").outerWidth(true) - tabOuterWidth; + //实际滚动宽度 + var scrollVal = 0; + if ($(".page-tabs-content").outerWidth() < visibleWidth) { + scrollVal = 0; + } else if (marginRightVal <= (visibleWidth - $(element).outerWidth(true) - $(element).next().outerWidth(true))) { + if ((visibleWidth - $(element).next().outerWidth(true)) > marginRightVal) { + scrollVal = marginLeftVal; + var tabElement = element; + while ((scrollVal - $(tabElement).outerWidth()) > ($(".page-tabs-content").outerWidth() - visibleWidth)) { + scrollVal -= $(tabElement).prev().outerWidth(); + tabElement = $(tabElement).prev(); + } + } + } else if (marginLeftVal > (visibleWidth - $(element).outerWidth(true) - $(element).prev().outerWidth(true))) { + scrollVal = marginLeftVal - $(element).prev().outerWidth(true); + } + $('.page-tabs-content').animate({ + marginLeft: 0 - scrollVal + 'px' + }, + "fast"); + } + + //查看左侧隐藏的选项卡 + function scrollTabLeft() { + var marginLeftVal = Math.abs(parseInt($('.page-tabs-content').css('margin-left'))); + // 可视区域非tab宽度 + var tabOuterWidth = calSumWidth($(".content-tabs").children().not(".menuTabs")); + //可视区域tab宽度 + var visibleWidth = $(".content-tabs").outerWidth(true) - tabOuterWidth; + //实际滚动宽度 + var scrollVal = 0; + if (($(".page-tabs-content").width()) < visibleWidth) { + return false; + } else { + var tabElement = $(".menuTab:first"); + var offsetVal = 0; + while ((offsetVal + $(tabElement).outerWidth(true)) <= marginLeftVal) { //找到离当前tab最近的元素 + offsetVal += $(tabElement).outerWidth(true); + tabElement = $(tabElement).next(); + } + offsetVal = 0; + if (calSumWidth($(tabElement).prevAll()) > visibleWidth) { + while ((offsetVal + $(tabElement).outerWidth(true)) < (visibleWidth) && tabElement.length > 0) { + offsetVal += $(tabElement).outerWidth(true); + tabElement = $(tabElement).prev(); + } + scrollVal = calSumWidth($(tabElement).prevAll()); + } + } + $('.page-tabs-content').animate({ + marginLeft: 0 - scrollVal + 'px' + }, + "fast"); + } + + //查看右侧隐藏的选项卡 + function scrollTabRight() { + var marginLeftVal = Math.abs(parseInt($('.page-tabs-content').css('margin-left'))); + // 可视区域非tab宽度 + var tabOuterWidth = calSumWidth($(".content-tabs").children().not(".menuTabs")); + //可视区域tab宽度 + var visibleWidth = $(".content-tabs").outerWidth(true) - tabOuterWidth; + //实际滚动宽度 + var scrollVal = 0; + if ($(".page-tabs-content").width() < visibleWidth) { + return false; + } else { + var tabElement = $(".menuTab:first"); + var offsetVal = 0; + while ((offsetVal + $(tabElement).outerWidth(true)) <= marginLeftVal) { //找到离当前tab最近的元素 + offsetVal += $(tabElement).outerWidth(true); + tabElement = $(tabElement).next(); + } + offsetVal = 0; + while ((offsetVal + $(tabElement).outerWidth(true)) < (visibleWidth) && tabElement.length > 0) { + offsetVal += $(tabElement).outerWidth(true); + tabElement = $(tabElement).next(); + } + scrollVal = calSumWidth($(tabElement).prevAll()); + if (scrollVal > 0) { + $('.page-tabs-content').animate({ + marginLeft: 0 - scrollVal + 'px' + }, + "fast"); + } + } + } + + //通过遍历给菜单项加上data-index属性 + $(".menuItem").each(function(index) { + if (!$(this).attr('data-index')) { + $(this).attr('data-index', index); + } + }); + + function menuItem() { + // 获取标识数据 + var dataUrl = $(this).attr('href'); + dataIndex = $(this).data('index'); + menuName = $.trim($(this).text()); + currentMenuId = $(this).attr('id'); + flag = true; + $(".nav ul li, .nav li").removeClass("selected"); + $(this).parent("li").addClass("selected"); + setIframeUrl($(this).attr("href")); + if (dataUrl == undefined || $.trim(dataUrl).length == 0) return false; + + // 选项卡菜单已存在 + $('.menuTab').each(function() { + if ($(this).data('id') == dataUrl) { + if (!$(this).hasClass('active')) { + $(this).addClass('active').siblings('.menuTab').removeClass('active'); + scrollToTab(this); + // 显示tab对应的内容区 + $('.mainContent .RuoYi_iframe').each(function() { + if ($(this).data('id') == dataUrl) { + $(this).show().siblings('.RuoYi_iframe').hide(); + return false; + } + }); + } + flag = false; + return false; + } + }); + // 选项卡菜单不存在 + if (flag) { + var str = '' + menuName + ' '; + $('.menuTab').removeClass('active'); + + // 添加选项卡对应的iframe + var str1 = ''; + $('.mainContent').find('iframe.RuoYi_iframe').hide().parents('.mainContent').append(str1); + + $.modal.loading("数据加载中,请稍后..."); + + $('.mainContent iframe:visible').load(function () { + $.modal.closeLoading(); + }); + + // 添加选项卡 + $('.menuTabs .page-tabs-content').append(str); + scrollToTab($('.menuTab.active')); + } + return false; + } + + function menuBlank() { + // 新窗口打开外网以http://开头,如http://ruoyi.vip + var dataUrl = $(this).attr('href'); + window.open(dataUrl); + return false; + } + + $('.menuItem').on('click', menuItem); + + $('.menuBlank').on('click', menuBlank); + + // 关闭选项卡菜单 + function closeTab() { + var closeTabId = $(this).parents('.menuTab').data('id'); + var currentWidth = $(this).parents('.menuTab').width(); + var panelUrl = $(this).parents('.menuTab').data('panel'); + // 当前元素处于活动状态 + if ($(this).parents('.menuTab').hasClass('active')) { + + // 当前元素后面有同辈元素,使后面的一个元素处于活动状态 + if ($(this).parents('.menuTab').next('.menuTab').size()) { + + var toShow = $(this).parents('.menuTab').next('.menuTab:eq(0)'); + var activeId = toShow.data('id'); + currentMenuId = toShow.attr('id'); + $(this).parents('.menuTab').next('.menuTab:eq(0)').addClass('active'); + + $('.mainContent .RuoYi_iframe').each(function() { + if ($(this).data('id') == activeId) { + $(this).show().siblings('.RuoYi_iframe').hide(); + return false; + } + }); + + var marginLeftVal = parseInt($('.page-tabs-content').css('margin-left')); + if (marginLeftVal < 0) { + $('.page-tabs-content').animate({ + marginLeft: (marginLeftVal + currentWidth) + 'px' + }, + "fast"); + } + + // 移除当前选项卡 + $(this).parents('.menuTab').remove(); + + // 移除tab对应的内容区 + $('.mainContent .RuoYi_iframe').each(function() { + if ($(this).data('id') == closeTabId) { + $(this).remove(); + return false; + } + }); + } + + // 当前元素后面没有同辈元素,使当前元素的上一个元素处于活动状态 + if ($(this).parents('.menuTab').prev('.menuTab').size()) { + var toShow = $(this).parents('.menuTab').prev('.menuTab:last'); + var activeId = toShow.data('id'); + currentMenuId = toShow.attr('id'); + $(this).parents('.menuTab').prev('.menuTab:last').addClass('active'); + $('.mainContent .RuoYi_iframe').each(function() { + if ($(this).data('id') == activeId) { + $(this).show().siblings('.RuoYi_iframe').hide(); + return false; + } + }); + + // 移除当前选项卡 + $(this).parents('.menuTab').remove(); + + // 移除tab对应的内容区 + $('.mainContent .RuoYi_iframe').each(function() { + if ($(this).data('id') == closeTabId) { + $(this).remove(); + return false; + } + }); + + if($.common.isNotEmpty(panelUrl)){ + $('.menuTab[data-id="' + panelUrl + '"]').addClass('active').siblings('.menuTab').removeClass('active'); + $('.mainContent .RuoYi_iframe').each(function() { + if ($(this).data('id') == panelUrl) { + $(this).show().siblings('.RuoYi_iframe').hide(); + return false; + } + }); + } + } + } + // 当前元素不处于活动状态 + else { + // 移除当前选项卡 + $(this).parents('.menuTab').remove(); + + // 移除相应tab对应的内容区 + $('.mainContent .RuoYi_iframe').each(function() { + if ($(this).data('id') == closeTabId) { + $(this).remove(); + return false; + } + }); + } + scrollToTab($('.menuTab.active')); + return false; + } + + $('.menuTabs').on('click', '.menuTab i', closeTab); + + //滚动到已激活的选项卡 + function showActiveTab() { + scrollToTab($('.menuTab.active')); + } + $('.tabShowActive').on('click', showActiveTab); + + // 点击选项卡菜单 + function activeTab() { + if (!$(this).hasClass('active')) { + var currentId = $(this).data('id'); + currentMenuId = $(this).attr('id'); + // 显示tab对应的内容区 + $('.mainContent .RuoYi_iframe').each(function() { + if ($(this).data('id') == currentId) { + $(this).show().siblings('.RuoYi_iframe').hide(); + return false; + } + }); + $(this).addClass('active').siblings('.menuTab').removeClass('active'); + scrollToTab(this); + } + } + + // 点击选项卡菜单 + $('.menuTabs').on('click', '.menuTab', activeTab); + + // 刷新iframe + function refreshTab() { + var currentId = $('.page-tabs-content').find('.active').attr('data-id'); + var target = $('.RuoYi_iframe[data-id="' + currentId + '"]'); + var url = target.attr('src'); + target.attr('src', url).ready(); + } + + // 页签全屏 + function fullScreenTab() { + var currentId = $('.page-tabs-content').find('.active').attr('data-id'); + var target = $('.RuoYi_iframe[data-id="' + currentId + '"]'); + target.fullScreen(true); + } + + // 关闭当前选项卡 + function tabCloseCurrent() { + $('.page-tabs-content').find('.active i').trigger("click"); + } + + //关闭其他选项卡 + function tabCloseOther() { + $('.page-tabs-content').children("[data-id]").not(":first").not(".active").each(function() { + $('.RuoYi_iframe[data-id="' + $(this).data('id') + '"]').remove(); + $(this).remove(); + }); + $('.page-tabs-content').css("margin-left", "0"); + } + + // 关闭全部选项卡 + function tabCloseAll() { + $('.page-tabs-content').children("[data-id]").not(":first").each(function() { + $('.RuoYi_iframe[data-id="' + $(this).data('id') + '"]').remove(); + $(this).remove(); + }); + $('.page-tabs-content').children("[data-id]:first").each(function() { + $('.RuoYi_iframe[data-id="' + $(this).data('id') + '"]').show(); + $(this).addClass("active"); + }); + $('.page-tabs-content').css("margin-left", "0"); + } + + + // 全屏显示 + $('#fullScreen').on('click', function () { + $(document).toggleFullScreen(); + }); + + // 页签刷新按钮 + $('.tabReload').on('click', refreshTab); + + // 页签全屏按钮 + $('.tabFullScreen').on('click', fullScreenTab); + + // 双击选项卡全屏显示 + $('.menuTabs').on('dblclick', '.menuTab', activeTabMax); + + // 左移按扭 + $('.tabLeft').on('click', scrollTabLeft); + + // 右移按扭 + $('.tabRight').on('click', scrollTabRight); + + // 关闭当前 + $('.tabCloseCurrent').on('click', tabCloseCurrent); + + // 关闭其他 + $('.tabCloseOther').on('click', tabCloseOther); + + // 关闭全部 + $('.tabCloseAll').on('click', tabCloseAll); + + // tab全屏显示 + $('.tabMaxCurrent').on('click', function () { + $('.page-tabs-content').find('.active').trigger("dblclick"); + }); + + // 关闭全屏 + $('#ax_close_max').click(function(){ + $('#content-main').toggleClass('max'); + $('#ax_close_max').hide(); + }) + + // 双击选项卡全屏显示 + function activeTabMax() { + $('#content-main').toggleClass('max'); + $('#ax_close_max').show(); + } + + // 设置锚点 + function setIframeUrl(href) { + if($.common.equals("history", mode)) { + storage.set('publicPath', href); + } else { + var nowUrl = window.location.href; + var newUrl = nowUrl.substring(0, nowUrl.indexOf("#")); + window.location.href = newUrl + "#" + href; + } + } + + $(window).keydown(function(event) { + if (event.keyCode == 27) { + $('#content-main').removeClass('max'); + $('#ax_close_max').hide(); + } + }); + + window.onhashchange = function() { + var hash = location.hash; + var url = hash.substring(1, hash.length); + $('a[href$="' + url + '"]').click(); + }; + + // 右键菜单实现 + $.contextMenu({ + selector: ".menuTab", + trigger: 'right', + autoHide: true, + items: { + "close_current": { + name: "关闭当前", + icon: "fa-close", + callback: function(key, opt) { + opt.$trigger.find('i').trigger("click"); + } + }, + "close_other": { + name: "关闭其他", + icon: "fa-window-close-o", + callback: function(key, opt) { + setActiveTab(this); + tabCloseOther(); + } + }, + "close_left": { + name: "关闭左侧", + icon: "fa-reply", + callback: function(key, opt) { + setActiveTab(this); + this.prevAll('.menuTab').not(":last").each(function() { + if ($(this).hasClass('active')) { + setActiveTab(this); + } + $('.RuoYi_iframe[data-id="' + $(this).data('id') + '"]').remove(); + $(this).remove(); + }); + $('.page-tabs-content').css("margin-left", "0"); + } + }, + "close_right": { + name: "关闭右侧", + icon: "fa-share", + callback: function(key, opt) { + setActiveTab(this); + this.nextAll('.menuTab').each(function() { + $('.menuTab[data-id="' + $(this).data('id') + '"]').remove(); + $(this).remove(); + }); + } + }, + "close_all": { + name: "全部关闭", + icon: "fa-window-close", + callback: function(key, opt) { + tabCloseAll(); + } + }, + "step": "---------", + "full": { + name: "全屏显示", + icon: "fa-arrows-alt", + callback: function(key, opt) { + setActiveTab(this); + var target = $('.RuoYi_iframe[data-id="' + this.data('id') + '"]'); + target.fullScreen(true); + } + }, + "refresh": { + name: "刷新页面", + icon: "fa-refresh", + callback: function(key, opt) { + setActiveTab(this); + var target = $('.RuoYi_iframe[data-id="' + this.data('id') + '"]'); + var url = target.attr('src'); + $.modal.loading("数据加载中,请稍后..."); + target.attr('src', url).load(function () { + $.modal.closeLoading(); + }); + } + }, + "open": { + name: "新窗口打开", + icon: "fa-link", + callback: function(key, opt) { + var target = $('.RuoYi_iframe[data-id="' + this.data('id') + '"]'); + window.open(target.attr('src')); + } + }, + } + }) }); \ No newline at end of file diff --git a/ruoyi-admin/src/main/resources/templates/index.html b/ruoyi-admin/src/main/resources/templates/index.html index 15b0f6fe0..5ab14d044 100644 --- a/ruoyi-admin/src/main/resources/templates/index.html +++ b/ruoyi-admin/src/main/resources/templates/index.html @@ -1,317 +1,319 @@ - - - - - - - 若依系统首页 - - - - - - - - - - - -
- - - - - - -
- -
- - - - 刷新 -
- - - -
- -
- -
- -
- - - - - - - - - - - - - - - + + + + + + + 若依系统首页 + + + + + + + + + + + +
+ + + + + + +
+ +
+ + + + 刷新 +
+ + + +
+ +
+ +
+ +
+ + + + + + + + + + + + + + + diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataScope.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataScope.java index b0d4b7ffc..248058368 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataScope.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataScope.java @@ -11,17 +11,13 @@ import java.lang.annotation.Target; * * @author ruoyi */ -@Target(ElementType.METHOD) +@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface DataScope { /** - * 部门表的别名 + * 业务表的所属用户的字段名称:过滤仅本人的数据权限, + * 该字段的类型为:{@link com.ruoyi.system.domain.SysUser} */ - public String deptAlias() default ""; - - /** - * 用户表的别名 - */ - public String userAlias() default ""; + String userFieldName() default ""; } diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataScopes.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataScopes.java new file mode 100644 index 000000000..0da657142 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataScopes.java @@ -0,0 +1,25 @@ +package com.ruoyi.common.annotation; + +public enum DataScopes implements Comparable{ + /** + * 全部数据权限 + */ + DATA_SCOPE_ALL, + /** + * 自定数据权限 + */ + DATA_SCOPE_CUSTOM, + /** + * 部门数据权限 + */ + DATA_SCOPE_DEPT, + /** + * 部门及以下数据权限 + */ + DATA_SCOPE_DEPT_AND_CHILD, + /** + * 仅本人数据权限 + */ + DATA_SCOPE_SELF, + ; +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/base/BaseRepository.java b/ruoyi-common/src/main/java/com/ruoyi/common/base/BaseRepository.java index 4e8b0d457..6bce9515b 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/base/BaseRepository.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/base/BaseRepository.java @@ -5,9 +5,11 @@ import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.querydsl.QuerydslPredicateExecutor; import org.springframework.data.repository.NoRepositoryBean; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.Predicate; + @NoRepositoryBean public interface BaseRepository extends JpaRepository, JpaSpecificationExecutor, QuerydslPredicateExecutor { - } diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/base/BaseService.java b/ruoyi-common/src/main/java/com/ruoyi/common/base/BaseService.java index 0a5c78288..59c0a5ed4 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/base/BaseService.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/base/BaseService.java @@ -1,9 +1,6 @@ package com.ruoyi.common.base; -import com.querydsl.core.types.dsl.BooleanExpression; -import com.querydsl.core.types.dsl.ComparableExpression; -import com.querydsl.core.types.dsl.NumberPath; -import com.querydsl.core.types.dsl.StringPath; +import com.querydsl.core.types.dsl.*; import com.ruoyi.common.utils.querydsl.ExpressionUtils; public class BaseService { @@ -12,7 +9,7 @@ public class BaseService { return ExpressionUtils.buildLike(path, value); } - protected > BooleanExpression buildEqual(ComparableExpression path, T value){ + protected > BooleanExpression buildEqual(ComparableExpressionBase path, T value){ return ExpressionUtils.buildEqual(path, value); } diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/controller/BaseController.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/controller/BaseController.java index 25f13cdc1..69d4bf49c 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/core/controller/BaseController.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/controller/BaseController.java @@ -171,4 +171,5 @@ public class BaseController { public String redirect(String url) { return StringUtils.format("redirect:{}", url); } + } diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/repository/DataScopeRepository.java b/ruoyi-common/src/main/java/com/ruoyi/common/repository/DataScopeRepository.java new file mode 100644 index 000000000..97ca1debb --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/repository/DataScopeRepository.java @@ -0,0 +1,230 @@ +package com.ruoyi.common.repository; + +import com.querydsl.core.types.OrderSpecifier; +import com.querydsl.core.types.Predicate; +import org.springframework.data.domain.Example; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.data.jpa.domain.Specification; +import org.springframework.data.jpa.repository.support.*; +import org.springframework.data.querydsl.QuerydslPredicateExecutor; +import org.springframework.lang.Nullable; +import org.springframework.util.Assert; + +import javax.persistence.EntityManager; +import java.io.Serializable; +import java.util.List; +import java.util.Optional; + + +public class DataScopeRepository implements JpaRepositoryImplementation, + QuerydslPredicateExecutor { + + private @Nullable + CrudMethodMetadata metadata; + + private SimpleJpaRepository simpleJpaRepository; + private QuerydslPredicateExecutor querydslPredicateExecutor; + + public DataScopeRepository(JpaEntityInformation entityInformation, EntityManager entityManager) { + Assert.notNull(entityInformation, "JpaEntityInformation must not be null!"); + Assert.notNull(entityManager, "EntityManager must not be null!"); + this.simpleJpaRepository = new SimpleJpaRepository(entityInformation, entityManager); + } + + public DataScopeRepository(Class domainClass, EntityManager em) { + this.simpleJpaRepository = new SimpleJpaRepository(JpaEntityInformationSupport.getEntityInformation(domainClass, em), em); + } + + @Override + public void setRepositoryMethodMetadata(CrudMethodMetadata crudMethodMetadata) { + this.metadata = crudMethodMetadata; + simpleJpaRepository.setRepositoryMethodMetadata(crudMethodMetadata); + } + + @Override + public List findAll() { + return simpleJpaRepository.findAll(); + } + + @Override + public List findAll(Sort sort) { + return null; + } + + @Override + public Page findAll(Pageable pageable) { + return null; + } + + @Override + public List findAllById(Iterable ids) { + return null; + } + + @Override + public long count() { + return 0; + } + + @Override + public void deleteById(ID id) { + + } + + @Override + public void delete(T entity) { + + } + + @Override + public void deleteAll(Iterable entities) { + + } + + @Override + public void deleteAll() { + + } + + @Override + public S save(S entity) { + return null; + } + + @Override + public List saveAll(Iterable entities) { + return null; + } + + @Override + public Optional findById(ID id) { + return Optional.empty(); + } + + @Override + public boolean existsById(ID id) { + return false; + } + + @Override + public void flush() { + + } + + @Override + public S saveAndFlush(S entity) { + return null; + } + + @Override + public void deleteInBatch(Iterable entities) { + + } + + @Override + public void deleteAllInBatch() { + + } + + @Override + public T getOne(ID id) { + return null; + } + + @Override + public Optional findOne(Example example) { + return Optional.empty(); + } + + @Override + public List findAll(Example example) { + return null; + } + + @Override + public List findAll(Example example, Sort sort) { + return null; + } + + @Override + public Page findAll(Example example, Pageable pageable) { + return null; + } + + @Override + public long count(Example example) { + return 0; + } + + @Override + public boolean exists(Example example) { + return false; + } + + @Override + public Optional findOne(Specification spec) { + return Optional.empty(); + } + + @Override + public List findAll(Specification spec) { + return null; + } + + @Override + public Page findAll(Specification spec, Pageable pageable) { + return null; + } + + @Override + public List findAll(Specification spec, Sort sort) { + return null; + } + + @Override + public long count(Specification spec) { + return 0; + } + + @Override + public Optional findOne(Predicate predicate) { + return querydslPredicateExecutor.findOne(predicate); + } + + @Override + public Iterable findAll(Predicate predicate) { + return querydslPredicateExecutor.findAll(predicate); + } + + @Override + public Iterable findAll(Predicate predicate, Sort sort) { + return querydslPredicateExecutor.findAll(predicate, sort); + } + + @Override + public Iterable findAll(Predicate predicate, OrderSpecifier... orders) { + return querydslPredicateExecutor.findAll(predicate, orders); + } + + @Override + public Iterable findAll(OrderSpecifier... orders) { + return querydslPredicateExecutor.findAll(orders); + } + + @Override + public Page findAll(Predicate predicate, Pageable pageable) { + return querydslPredicateExecutor.findAll(predicate, pageable); + } + + @Override + public long count(Predicate predicate) { + return querydslPredicateExecutor.count(predicate); + } + + @Override + public boolean exists(Predicate predicate) { + return querydslPredicateExecutor.exists(predicate); + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/querydsl/ExpressionUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/querydsl/ExpressionUtils.java index d6cdd56a3..d6019804f 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/querydsl/ExpressionUtils.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/querydsl/ExpressionUtils.java @@ -1,9 +1,6 @@ package com.ruoyi.common.utils.querydsl; -import com.querydsl.core.types.dsl.BooleanExpression; -import com.querydsl.core.types.dsl.ComparableExpression; -import com.querydsl.core.types.dsl.NumberPath; -import com.querydsl.core.types.dsl.StringPath; +import com.querydsl.core.types.dsl.*; /** * QueryDsl 构建查询条件的工具类 @@ -35,7 +32,7 @@ public class ExpressionUtils { * @param * @return */ - public static > BooleanExpression buildEqual(ComparableExpression path, T value){ + public static > BooleanExpression buildEqual(ComparableExpressionBase path, T value){ return path.eq(value); } diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java index 88c1b52fe..7412b9047 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java @@ -1,20 +1,32 @@ package com.ruoyi.framework.aspectj; -import java.lang.reflect.Method; - -import org.aspectj.lang.JoinPoint; -import org.aspectj.lang.Signature; -import org.aspectj.lang.annotation.Aspect; -import org.aspectj.lang.annotation.Before; -import org.aspectj.lang.annotation.Pointcut; -import org.aspectj.lang.reflect.MethodSignature; -import org.springframework.stereotype.Component; +import com.querydsl.core.types.ExpressionUtils; +import com.querydsl.core.types.Predicate; import com.ruoyi.common.annotation.DataScope; import com.ruoyi.common.core.domain.BaseEntity; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.framework.util.ShiroUtils; import com.ruoyi.system.domain.SysRole; import com.ruoyi.system.domain.SysUser; +import com.ruoyi.system.service.ISysUserService; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.Signature; +import org.aspectj.lang.annotation.After; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Before; +import org.aspectj.lang.annotation.Pointcut; +import org.aspectj.lang.reflect.MethodSignature; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.Root; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; /** * 数据过滤处理 @@ -24,35 +36,11 @@ import com.ruoyi.system.domain.SysUser; @Aspect @Component public class DataScopeAspect { - /** - * 全部数据权限 - */ - public static final String DATA_SCOPE_ALL = "1"; - /** - * 自定数据权限 - */ - public static final String DATA_SCOPE_CUSTOM = "2"; - - /** - * 部门数据权限 - */ - public static final String DATA_SCOPE_DEPT = "3"; - - /** - * 部门及以下数据权限 - */ - public static final String DATA_SCOPE_DEPT_AND_CHILD = "4"; - - /** - * 仅本人数据权限 - */ - public static final String DATA_SCOPE_SELF = "5"; - - /** - * 数据权限过滤关键字 - */ - public static final String DATA_SCOPE = "dataScope"; + @Autowired + private ISysUserService userService; + @PersistenceContext + private EntityManager entityManager; // 配置织入点 @Pointcut("@annotation(com.ruoyi.common.annotation.DataScope)") @@ -64,19 +52,25 @@ public class DataScopeAspect { handleDataScope(point); } + @After("dataScopePointCut()") + public void doAfter(JoinPoint point) throws Throwable{ + DataScopeContextHolder.clear(); + } + protected void handleDataScope(final JoinPoint joinPoint) { // 获得注解 + SysUser currentUser = ShiroUtils.getSysUser(); DataScope controllerDataScope = getAnnotationLog(joinPoint); + if (controllerDataScope == null) { return; } // 获取当前的用户 - SysUser currentUser = ShiroUtils.getSysUser(); + if (currentUser != null) { // 如果是超级管理员,则不过滤数据 if (!currentUser.isAdmin()) { - dataScopeFilter(joinPoint, currentUser, controllerDataScope.deptAlias(), - controllerDataScope.userAlias()); + dataScopeFilter(joinPoint, currentUser, controllerDataScope); } } } @@ -86,40 +80,30 @@ public class DataScopeAspect { * * @param joinPoint 切点 * @param user 用户 - * @param deptAlias 别名 */ - public static void dataScopeFilter(JoinPoint joinPoint, SysUser user, String deptAlias, String userAlias) { - StringBuilder sqlString = new StringBuilder(); + private void dataScopeFilter(JoinPoint joinPoint, SysUser user, DataScope controllerDataScope) { + user = userService.selectUserWithRolesAndPostsById(user.getUserId()); - for (SysRole role : user.getRoles()) { - String dataScope = role.getDataScope(); - if (DATA_SCOPE_ALL.equals(dataScope)) { - sqlString = new StringBuilder(); - break; - } else if (DATA_SCOPE_CUSTOM.equals(dataScope)) { - sqlString.append(StringUtils.format( - " OR {}.dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id = {} ) ", deptAlias, - role.getRoleId())); - } else if (DATA_SCOPE_DEPT.equals(dataScope)) { - sqlString.append(StringUtils.format(" OR {}.dept_id = {} ", deptAlias, user.getDept().getDeptId())); - } else if (DATA_SCOPE_DEPT_AND_CHILD.equals(dataScope)) { - sqlString.append(StringUtils.format( - " OR {}.dept_id IN ( SELECT dept_id FROM sys_dept WHERE dept_id = {} or find_in_set( {} , ancestors ) )", - deptAlias, user.getDept().getDeptId(), user.getDept().getDeptId())); - } else if (DATA_SCOPE_SELF.equals(dataScope)) { - if (StringUtils.isNotBlank(userAlias)) { - sqlString.append(StringUtils.format(" OR {}.user_id = {} ", userAlias, user.getUserId())); - } else { - // 数据权限为仅本人且没有userAlias别名不查询任何数据 - sqlString.append(" OR 1=0 "); - } + CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); + List predicates = new ArrayList<>(); + Set roles = user.getRoles(); + for(SysRole sysRole : roles){ + switch (sysRole.getDataScope()){ + case DATA_SCOPE_DEPT: //当前部门 + break; + case DATA_SCOPE_SELF: //自己 + break; + case DATA_SCOPE_CUSTOM: //自定义 + break; + case DATA_SCOPE_DEPT_AND_CHILD: //子部门 + break; + default: + //无需过滤 + break; } } - if (StringUtils.isNotBlank(sqlString.toString())) { - BaseEntity baseEntity = (BaseEntity) joinPoint.getArgs()[0]; - baseEntity.getParams().put(DATA_SCOPE, " AND (" + sqlString.substring(4) + ")"); - } + DataScopeContextHolder.set(ExpressionUtils.anyOf(predicates)); } /** diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataScopeContextHolder.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataScopeContextHolder.java new file mode 100644 index 000000000..4a6ad0e6b --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataScopeContextHolder.java @@ -0,0 +1,20 @@ +package com.ruoyi.framework.aspectj; + +import com.querydsl.core.types.Predicate; + +public class DataScopeContextHolder { + + private static ThreadLocal threadLocal = new ThreadLocal<>(); + + public static void set(Predicate predicate){ + threadLocal.set(predicate); + } + + public static void clear(){ + threadLocal.remove(); + } + + public static Predicate get(){ + return threadLocal.get(); + } +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/MySpecification.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/MySpecification.java new file mode 100644 index 000000000..5a94592cf --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/MySpecification.java @@ -0,0 +1,60 @@ +package com.ruoyi.framework.aspectj; + +import com.ruoyi.common.utils.spring.SpringUtils; +import com.ruoyi.framework.util.ShiroUtils; +import com.ruoyi.system.domain.SysRole; +import com.ruoyi.system.domain.SysUser; +import com.ruoyi.system.service.ISysUserService; +import org.springframework.data.jpa.domain.Specification; + +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.Predicate; +import javax.persistence.criteria.Root; +import java.util.ArrayList; +import java.util.List; + +public abstract class MySpecification implements Specification { + + @Override + public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder criteriaBuilder) { + List predicates = new ArrayList<>(); + + //custom filter + addPredicate(root, query, criteriaBuilder, predicates); + + //datascope filter + Predicate predicate = addDataScopeFilter(root, query, criteriaBuilder); + predicates.add(predicate); + + //条件之间是 and 关系 + return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()])); + } + + public abstract void addPredicate(Root root, CriteriaQuery query, CriteriaBuilder criteriaBuilder, List predicates); + + protected Predicate addDataScopeFilter(Root root, CriteriaQuery query, CriteriaBuilder criteriaBuilder){ + List predicates = new ArrayList<>(); + + ISysUserService userService = SpringUtils.getBean(ISysUserService.class); + SysUser sysUser = userService.selectUserWithRolesAndPostsById(ShiroUtils.getUserId()); + + if(!sysUser.isAdmin()){ + for(SysRole sysRole : sysUser.getRoles()){ + switch (sysRole.getDataScope()){ + case DATA_SCOPE_DEPT_AND_CHILD: + break; + case DATA_SCOPE_CUSTOM: + break; + case DATA_SCOPE_SELF: + break; + case DATA_SCOPE_DEPT: + break; + } + } + } + + //条件之间是 or 关系 + return criteriaBuilder.or(predicates.toArray(new Predicate[predicates.size()])); + } +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRole.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRole.java index 0dd028a41..b792e4cce 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRole.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRole.java @@ -1,5 +1,6 @@ package com.ruoyi.system.domain; +import com.ruoyi.common.annotation.DataScopes; import com.ruoyi.common.annotation.Excel; import com.ruoyi.common.annotation.Excel.ColumnType; import com.ruoyi.common.core.domain.BaseEntity; @@ -54,7 +55,7 @@ public class SysRole extends BaseEntity { * 数据范围(1:所有数据权限;2:自定义数据权限;3:本部门数据权限;4:本部门及以下数据权限) */ @Excel(name = "数据范围", readConverterExp = "1=所有数据权限,2=自定义数据权限,3=本部门数据权限,4=本部门及以下数据权限") - private String dataScope; + private DataScopes dataScope; /** * 角色状态(0正常 1停用) @@ -111,11 +112,11 @@ public class SysRole extends BaseEntity { return roleId != null && 1L == roleId; } - public String getDataScope() { + public DataScopes getDataScope() { return dataScope; } - public void setDataScope(String dataScope) { + public void setDataScope(DataScopes dataScope) { this.dataScope = dataScope; } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/converter/DataScopesConverter.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/converter/DataScopesConverter.java new file mode 100644 index 000000000..f4244f2a2 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/converter/DataScopesConverter.java @@ -0,0 +1,23 @@ +package com.ruoyi.system.domain.converter; + +import com.ruoyi.common.annotation.DataScopes; + +import javax.persistence.AttributeConverter; +import javax.persistence.Converter; +import java.util.Arrays; + +@Converter(autoApply = true) +public class DataScopesConverter implements AttributeConverter { + @Override + public String convertToDatabaseColumn(DataScopes attribute) { + return attribute != null ? attribute.name() : null; + } + + @Override + public DataScopes convertToEntityAttribute(String dbData) { + return Arrays.stream(DataScopes.values()) + .filter(dataScopes -> dataScopes.name().equals(dbData)) + .findFirst() + .orElse(DataScopes.DATA_SCOPE_ALL); + } +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysRoleService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysRoleService.java index f7b3a3b47..8c7fc25cb 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysRoleService.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysRoleService.java @@ -1,6 +1,7 @@ package com.ruoyi.system.service; import com.ruoyi.system.domain.SysRole; +import com.ruoyi.system.domain.SysUser; import com.ruoyi.system.domain.SysUserRole; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; @@ -18,9 +19,10 @@ public interface ISysRoleService { * 根据条件分页查询角色数据 * * @param role 角色信息 + * @param user * @return 角色数据集合信息 */ - public Page selectRoleList(SysRole role, Pageable pageable); + public Page selectRoleList(SysRole role, Pageable pageable, SysUser user); /** * 根据用户ID查询角色 diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java index 9af23ec75..69239aebe 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java @@ -1,10 +1,12 @@ package com.ruoyi.system.service; +import com.ruoyi.system.domain.SysDept; import com.ruoyi.system.domain.SysUser; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import java.util.List; +import java.util.Set; /** * 用户 业务层 @@ -169,4 +171,6 @@ public interface ISysUserService { * @return 结果 */ public void changeStatus(SysUser user); + + Set getUserRoleDepts(Long userId); } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/base/BusinessService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/base/BusinessService.java new file mode 100644 index 000000000..50899506c --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/base/BusinessService.java @@ -0,0 +1,46 @@ +package com.ruoyi.system.service.base; + +import com.querydsl.core.types.ExpressionUtils; +import com.querydsl.core.types.Predicate; +import com.querydsl.core.types.dsl.ListPath; +import com.ruoyi.common.base.BaseService; +import com.ruoyi.system.domain.QSysDept; +import com.ruoyi.system.domain.SysDept; +import com.ruoyi.system.service.ISysUserService; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +public class BusinessService extends BaseService { + + @Autowired + private ISysUserService userService; + + /** + * 过滤数据权限 + * @param path dept属性 + * @param userId 当前用户id + * @return + */ + protected Predicate buildDataPermission(QSysDept path, Long userId){ + Set depts = userService.getUserRoleDepts(userId); + List predicates = new ArrayList<>(); + predicates.add(ExpressionUtils.in(path, depts)); + return ExpressionUtils.allOf(predicates); + } + + /** + * 过滤数据权限 + * @param path dept属性 + * @param userId 当前用户id + * @return + */ + protected Predicate buildDataPermission(ListPath path, Long userId){ + Set depts = userService.getUserRoleDepts(userId); + List predicates = new ArrayList<>(); + predicates.add(ExpressionUtils.in(path.any(), depts)); + return ExpressionUtils.allOf(predicates); + } +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java index ec1cb2bcb..9ee9347e3 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java @@ -2,7 +2,7 @@ package com.ruoyi.system.service.impl; import com.querydsl.core.types.ExpressionUtils; import com.querydsl.core.types.Predicate; -import com.ruoyi.common.base.BaseService; +import com.ruoyi.common.annotation.DataScope; import com.ruoyi.common.constant.UserConstants; import com.ruoyi.common.core.domain.BaseEntity; import com.ruoyi.common.core.text.Convert; @@ -15,6 +15,7 @@ import com.ruoyi.system.domain.SysUserRole; import com.ruoyi.system.repository.SysRoleRepository; import com.ruoyi.system.repository.SysUserRepository; import com.ruoyi.system.service.ISysRoleService; +import com.ruoyi.system.service.base.BusinessService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; @@ -28,8 +29,9 @@ import java.util.*; * * @author ruoyi */ +@DataScope(userFieldName = "user") @Service -public class SysRoleServiceImpl extends BaseService implements ISysRoleService { +public class SysRoleServiceImpl extends BusinessService implements ISysRoleService { @Autowired private SysRoleRepository sysRoleRepository; @@ -40,14 +42,15 @@ public class SysRoleServiceImpl extends BaseService implements ISysRoleService { * 根据条件分页查询角色数据 * * @param role 角色信息 + * @param user * @return 角色数据集合信息 */ @Override - public Page selectRoleList(SysRole role, Pageable pageable) { - return sysRoleRepository.findAll(getPredicate(role), pageable); + public Page selectRoleList(SysRole role, Pageable pageable, SysUser user) { + return sysRoleRepository.findAll(getPredicate(role, user), pageable); } - private Predicate getPredicate(SysRole role){ + public Predicate getPredicate(SysRole role, SysUser user){ QSysRole qSysRole = QSysRole.sysRole; List predicates = new ArrayList<>(); predicates.add(buildEqual(qSysRole.delFlag, BaseEntity.NOT_DELETED)); @@ -60,8 +63,8 @@ public class SysRoleServiceImpl extends BaseService implements ISysRoleService { if(StringUtils.isNotEmpty(role.getRoleKey())){ predicates.add(buildLike(qSysRole.roleKey, role.getRoleKey())); } - if(StringUtils.isNotEmpty(role.getDataScope())){ - predicates.add(buildEqual(qSysRole.dataScope, role.getDataScope())); + if(role.getDataScope() != null){ + predicates.add(buildEqual(qSysRole.dataScope, role.getDataScope().name())); } if(role.getStartTime() != null){ predicates.add(buildGreaterThanOrEqualTo(qSysRole.createTime, role.getStartTime())); @@ -69,6 +72,7 @@ public class SysRoleServiceImpl extends BaseService implements ISysRoleService { if(role.getEndTime() != null){ predicates.add(buildLessThanOrEqualTo(qSysRole.createTime, role.getEndTime())); } +// predicates.add(buildDataPermission(qSysRole.depts, user.getUserId())); return ExpressionUtils.allOf(predicates); } @@ -108,7 +112,7 @@ public class SysRoleServiceImpl extends BaseService implements ISysRoleService { */ @Override public List selectRoleAll() { - return sysRoleRepository.findAll(getPredicate(new SysRole()), Pageable.unpaged()).getContent(); + return sysRoleRepository.findAll(getPredicate(new SysRole(), new SysUser()), Pageable.unpaged()).getContent(); } /** diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java index 2955b73e7..a4d967a4d 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java @@ -9,8 +9,10 @@ import com.ruoyi.common.exception.BusinessException; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.security.Md5Utils; import com.ruoyi.system.domain.QSysUser; +import com.ruoyi.system.domain.SysDept; import com.ruoyi.system.domain.SysRole; import com.ruoyi.system.domain.SysUser; +import com.ruoyi.system.repository.SysRoleRepository; import com.ruoyi.system.repository.SysUserRepository; import com.ruoyi.system.service.ISysConfigService; import com.ruoyi.system.service.ISysUserService; @@ -28,10 +30,7 @@ import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Root; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; -import java.util.Set; +import java.util.*; /** * 用户 业务层处理 @@ -44,9 +43,10 @@ public class SysUserServiceImpl extends BaseService implements ISysUserService { @Autowired private SysUserRepository sysUserRepository; - @Autowired private ISysConfigService configService; + @Autowired + private SysRoleRepository sysRoleRepository; /** * 根据条件分页查询用户列表 @@ -414,4 +414,15 @@ public class SysUserServiceImpl extends BaseService implements ISysUserService { public void changeStatus(SysUser user) { sysUserRepository.changeStatus(user.getStatus(), user.getUserId()); } + + public Set getUserRoleDepts(Long userId){ + SysUser user = sysUserRepository.findSysUserByDelFlagAndUserId(BaseEntity.NOT_DELETED, userId); + Set depts = new HashSet<>(); + Set roles = user.getRoles(); + for(SysRole sysRole : roles){ + sysRole = sysRoleRepository.findByRoleId(sysRole.getRoleId()); + depts.addAll(sysRole.getDepts()); + } + return depts; + } }