跳至主要內容
定制底部footer bug修复:切换tab时position fixed会抖动

bug描述

在element admin里面定制了footer组件,每个页面也可还有点区别,将分页和导出和一些其他操作放到footer,在切换页面的时候会有抖动

position:fixed是啥?有啥用

position:fixed是固定定位的意思,就是把一个DIV(footer)固定在页面的最底部,无论页面上面的内容如何滚动,页面下部的(footer)不动。

为什么切换tab的时候会抖动

当元素祖先的 transform、perspective、filter 或 backdrop-filter 属性非 none 时,容器由视口改为该祖先。


程序员诚哥大约 2 分钟若依若依前端
若依vue中字典Dict插件的研究

涉及的知识点

插件与组件的区别

Vue组件(component)用来构成你的App的业务模块,它的目标是App.vue。
Vue插件(plugin) 用来增强你的技术栈的功能模块, 它的目标是Vue本身。(插件是对Vue的功能的增强和补充)

插件的作用

插件通常用来为 Vue 添加全局功能。插件的功能范围没有严格的限制——一般有下面几种:
添加全局方法或者属性。如: vue-custom-element
添加全局资源:指令/过滤器/过渡等。如 vue-touch
通过全局混入来添加一些组件选项。如 vue-router
添加 Vue 实例方法,通过把它们添加到 Vue.prototype 上实现。
一个库,提供自己的 API,同时提供上面提到的一个或多个功能。如 vue-router


程序员诚哥大约 5 分钟若依若依前端
若依源码解析:DataScopeAspect实现数据范围的控制

源代码

@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";

    @Before("@annotation(controllerDataScope)")
    public void doBefore(JoinPoint point, DataScope controllerDataScope) throws Throwable
    {
        clearDataScope(point);
        handleDataScope(point, controllerDataScope);
    }

    protected void handleDataScope(final JoinPoint joinPoint, DataScope controllerDataScope)
    {
        // 获取当前的用户
        LoginUser loginUser = SecurityUtils.getLoginUser();
        if (StringUtils.isNotNull(loginUser))
        {
            SysUser currentUser = loginUser.getUser();
            // 如果是超级管理员,则不过滤数据
            if (StringUtils.isNotNull(currentUser) && !currentUser.isAdmin())
            {
                dataScopeFilter(joinPoint, currentUser, controllerDataScope.deptAlias(),
                        controllerDataScope.userAlias());
            }
        }
    }

    /**
     * 数据范围过滤
     *
     * @param joinPoint 切点
     * @param user 用户
     * @param userAlias 别名
     */
    public static void dataScopeFilter(JoinPoint joinPoint, SysUser user, String deptAlias, String userAlias)
    {
        StringBuilder sqlString = new StringBuilder();

        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.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.getDeptId(), user.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 ");
                }
            }
        }

        if (StringUtils.isNotBlank(sqlString.toString()))
        {
            Object params = joinPoint.getArgs()[0];
            if (StringUtils.isNotNull(params) && params instanceof BaseEntity)
            {
                BaseEntity baseEntity = (BaseEntity) params;
                baseEntity.getParams().put(DATA_SCOPE, " AND (" + sqlString.substring(4) + ")");
            }
        }
    }

    /**
     * 拼接权限sql前先清空params.dataScope参数防止注入
     */
    private void clearDataScope(final JoinPoint joinPoint)
    {
        Object params = joinPoint.getArgs()[0];
        if (StringUtils.isNotNull(params) && params instanceof BaseEntity)
        {
            BaseEntity baseEntity = (BaseEntity) params;
            baseEntity.getParams().put(DATA_SCOPE, "");
        }
    }
}

程序员诚哥大约 5 分钟若依若依后端源码解析
若依源码解析:pagehelper和mybaties进行分页

若依分页使用示例

@PreAuthorize("@ss.hasPermi('system:dict:list')")
    @GetMapping("/list")
    public TableDataInfo list(SysDictData dictData)
    {
        startPage();
        List<SysDictData> list = dictDataService.selectDictDataList(dictData);
        return getDataTable(list);
    }

程序员诚哥大约 5 分钟若依若依后端源码解析
若依源码解析:RuoYi-Vue权限系统设计

摘要

若依(RuoYi)是一款基于Spring Boot和Vue.js开发的快速开发平台,它的权限管理是通过RBAC(Role-based Access Control 基于角色的访问控制)模型来设计的。

RBAC模型将权限控制分为角色管理和权限管理两个部分。在若依中,角色是指对系统的一类用户或操作者的定义,而权限是指对系统中某个资源或操作的访问控制。通过为每个角色分配相应的权限,可以实现对系统的全面管理和控制。

具体来说,在若依中,权限管理包括以下几个方面:

  1. 菜单管理:通过对系统菜单进行管理,可以控制用户在系统中能够访问的页面和功能。

  2. 按钮权限:在系统中,某些操作需要特定的权限才能进行,例如删除、修改等操作。通过对按钮权限的控制,可以限制用户对系统的访问和操作。

  3. 数据权限:在某些情况下,需要根据用户的角色或部门来限制其对数据的访问。通过数据权限的设置,可以实现对数据的细粒度控制。

  4. API接口权限:在若依中,API也可以通过权限的方式进行控制。通过对API的权限进行管理,可以限制用户对API的访问和使用。


程序员诚哥大约 9 分钟若依若依后端源码解析
若依源码解析:RuoYi-Vue登录和鉴权的实现

摘要

若依(RuoYi)是一款基于 Spring Boot 和 Vue.js 的开源权限管理系统,若依登录和鉴权的实现还包含验证码的生成与校验,这是为了增加系统的安全性,防止恶意攻击和暴力破解等行为。其登录和鉴权实现主要包括以下几个步骤:

  1. 验证码生成
  • 前端页面:登录页面中的验证码显示区域,通常位于 Vue.js 的 src/views 目录下。
  • 验证码 API:后端应用的验证码接口。该接口接收请求并生成验证码图片,并将验证码字符保存在 Redis 或者内存中。
  1. 用户登录:用户在登录页面输入用户名和密码,点击登录按钮,将表单数据发送给后端 Spring Boot 应用。

程序员诚哥大约 16 分钟若依若依后端源码解析
若依源码解析:图片验证码生成

摘要

若依通过合理的验证码生成流程和相应的代码实现,为应用程序提供了生成图片验证码和基于数学运算的验证码文本的功能,以增加系统的安全性和防护能力。
本文讨论了若依(Ruoyi)生成图片验证码的过程以及相关代码。首先,我们了解了生成图片验证码的基本步骤,包括生成随机字符串、创建图片对象、绘制背景和文本、添加干扰线等。
接下来,我们分析了若依中的验证码生成控制器,它根据配置的验证码类型,在后台生成对应类型的验证码,并将验证码图片以Base64编码的形式返回给前端页面。
最后,我们解释了一个自定义的验证码文本生成器,它生成基于数学运算的验证码文本,要求用户进行计算并输入结果进行验证。这种验证码形式提高了安全性和防止自动化攻击的能力。


程序员诚哥大约 7 分钟若依若依后端源码解析
若依源码解析:用LoggingAspect进行日志处理

摘要

本文将深入探讨若依框架中的LoggingAspect切面的作用和重要性。LoggingAspect是若依框架中用于实现日志记录功能的切面组件,它通过切点和切面的概念,将日志记录逻辑与业务逻辑解耦,实现非侵入式的日志记录。文章首先介绍了切面编程和AOP的概念,然后重点讨论了LoggingAspect的作用,包括捕获方法调用、记录日志信息以及提供代码重用和可维护性等优势。此外,文章还解释了@Pointcut注解的作用,它用于定义切点表达式,精确定位目标方法。最后,文章强调了在logback.xml配置文件中为LoggingAspect设置日志记录级别的重要性,以便控制日志输出的详细程度。通过深入理解LoggingAspect,开发人员可以优化日志记录和追踪功能,提高应用程序的可维护性和可读性,从而更好地监测和排查问题。


程序员诚哥大约 6 分钟若依若依后端源码解析
2