数据权限的设计与实现系列8——前端筛选器组件Everright-filter集成框架开发1

背景

前面我们对筛选器组件进行了功能探索和技术验证,接下来就开始着手集成工作,融入一二三开发平台,打通前后端,最终让数据权限控制功能落地。
整体集成工作比较复杂,我们遵循由易到难的原则,先搭建出完整框架,再具体完善各组成部分。‍

实体配置

首先,是需要新建一个业务实体,来维护实体与数据权限规则对应关系,使用平台的低代码配置功能完成。

创建实体

新建一个实体,放在实体配置功能模块下,如下图:

平台根据实体配置的属性,自动生成一个同名的数据模型,如下图:

配置模型

点击“配置属性”按钮,为其配置模型属性,如下图:

这里面的属性只有 5 个,简单说一下。
模型标识:对应关系的关键属性,用来标记该数据权限规则对应着哪个实体模型。
表名:MybatisPlus 的数据权限插件,拦截 SQL 语句解析后能获取到表名,通过该属性来获取到具体的数据权限规则。
规则:对应着数据筛选器配置产生的规则,通过组件的 getData 方法获取,一方面,这里的规则用于解析处理后转换为数据权限控制的 SQL 语句;另一方面,如某个业务实体已配置了数据权限规则,需要通过组件的 setData 来加载后让用户查看或修改。
sql 片段:根据数据筛选器配置产生的规则解析处理后的 SQL 片段,即将解析转换工作放到数据权限规则配置阶段完成,解析一次,多次使用。
备注:对数据权限规则进行友好性描述,便于规则的维护。

配置视图

数据权限规则的维护,将会嵌入到实体模型中,因此不需要列表视图,因此只需要添加一个详情视图,如下图所示:


完成上述基本配置后,遵循平台配置流程,进行生成库表、生成代码、拷贝代码、配置权限项操作后,完成实体配置工作。这些基本操作在平台实体配置部分有详细说明,在此不再赘述。

功能实现

新增功能按钮

访问平台的实体配置功能模块下的实体功能菜单,列出平台中的已配置的业务实体,如下图:

我们选一个相对简单的系统参数实体作为框架开发的目标对象,点击对应的行记录后的配置按钮,打开实体配置页面,默认显示实体模型,我们在行记录上增加一个新按钮,命名为“数据权限”,如下图所示:

点击该按钮,打开上一章节,我们为实体模型数据权限对应表这个实体配置的详情视图,如下:

注:还有两个属性,模型标识和表名由系统自动生成,并不需要用户维护,因此做了隐藏处理。

添加数据筛选器组件

在平台生成的代码基础上,手工添加数据筛选器组件,把先前的功能探索的验证页面,改写成 vue2 的风格,集成到系统中来。
首先是引入组件和样式表:

import { EverrightFilter } from 'everright-filter'
import 'everright-filter/dist/style.css'

然后,如下图:

关于组件属性的设置,因为暂时不考虑多语言支持,因此语种 lang 直接固化为中文 zh-cn,类型 type 指定为 matrix(多维),采用函数的方式,绑定筛选条件。

远程获取筛选条件

这里我们将原来测试的静态数据(姓名、年龄),调整为请求后端服务,如下:

async getOptions() {
      const options = await this.$api.entityconfig.entityModelProperty.getFullPropertyListForFilter(
        this.entityData.modelId
      )
   
      return new Promise((resolve, reject) => {
        resolve({
          data: {
            options: options.data,
            operators: {
              Text: [
                {
                  label: '等于',
                  en_label: 'Equal',
                  style: 'noop'
                },
                {
                  label: '等于其中之一',
                  en_label: 'Equal to one of',
                  value: 'one_of',
                  style: 'tags'
                },
                {
                  label: '不等于',
                  en_label: 'Not equal',
                  value: 'not_equal',
                  style: 'noop'
                },
                {
                  label: '包含',
                  en_label: 'Contains',
                  value: 'contains',
                  style: 'noop'
                },
                {
                  label: '不包含',
                  en_label: 'Not contain',
                  value: 'not_contain',
                  style: 'noop'
                },
                {
                  label: '为空',
                  en_label: 'Empty',
                  value: 'empty',
                  style: 'none'
                },
                {
                  label: '不为空',
                  en_label: 'Not empty',
                  value: 'not_empty',
                  style: 'none'
                }
              ]
            }
          }
        })
      })
    }

后端服务是从平台的实体配置中拿到数据模型的属性元数据,转换成数据筛选器组件需要的格式,如下:

 /**
     * 获取完整属性列表,转换为过滤器需要的格式
     * 只取数据库存储的属性
     *
     * @param entityModelId 实体模型id
     * @return {@link ResponseEntity}<{@link Result}>
     */
    @GetMapping("/{entityModelId}/getFullPropertyListForFilter")
    @SystemLog(value = "实体模型属性-完整列表,转换为筛选器格式")
    @PreAuthorize("hasPermission(null,'entityconfig:entityModelProperty:query')")
    public ResponseEntity<Result> getFullPropertyListForFilter(@PathVariable String entityModelId) {
        // 构造查询条件

        List<EntityModelProperty> list = entityModelPropertyService.getFullPropertyByEntityModelId(entityModelId);
        // 转换vo
        List<EntityModelPropertyForFilterVO> entityModelPropertyVOList = new ArrayList<>();
        for (int i = 0; i < list.size(); i++) {
            // 非库表存储属性直接跳过
            if (list.get(i).getDatabaseStoreFlag().equals(YesOrNoEnum.NO.name())) {
                continue;
            }
            EntityModelPropertyForFilterVO vo = new EntityModelPropertyForFilterVO();
            vo.setLabel(list.get(i).getName());
            vo.setValue(list.get(i).getCode());
            vo.setRenderType("TEXT");
            vo.setOperatorKey("Text");
            entityModelPropertyVOList.add(vo);
        }
        return ResultUtil.success(entityModelPropertyVOList);
    }

这里新建了数据筛选器的视图对象 vo,如下:

package tech.abc.platform.entityconfig.vo;


import lombok.Data;
import lombok.experimental.Accessors;

/**
 * 专用于数据筛选器的实体模型属性 视图对象类
 *
 * @author wqliu
 * @date 2024-08-05
 */
@Data
@Accessors(chain = true)
public class EntityModelPropertyForFilterVO {
    /**
     * 标签
     */
    private String label;

    /**
     * 编码
     */
    private String value;

    /**
     * 控件类型
     */
    private String renderType;

    /**
     * 操作符
     */
    private String operatorKey;

}

注:目前我们的核心任务是搭建框架,把整体串起来,运转起来后再完善细节,因此各部分设计和实现从简,比如所有的模型属性的展示控件暂都按文本类处理。

实现效果如下:

下拉列表中可以正常显示通过远程服务拿到的实体属性列表了,并可以作为筛选条件来使用了,如下图:

生成规则

在表单上添加一个按钮,命名为“生成规则”,点击后,调用筛选器组件的 getData 方法,生成规则 json,如下:

generateRule() {   
   this.entityData.rule = JSON.stringify(this.$refs.everrightFilter.getData(), null, '\t')
}

效果如下:

注:该地方曾尝试做成筛选器任何调整自动生成规则的方式,通过组件的 listener 机制,监听 triggerChange 事件,如下图所示

  handleListener({ type, data }) { 
    if (type == 'triggerChange') {
      this.generateRule()
    }   
  }

当添加条件时,控制台会报错,如下:

进一步打印 console.log(this.$refs.everrightFilter),发现能拿到筛选器对象,且 getData 方法也存在,如下图:

但是实际会报找不到 getData 方法,原因不明。
考虑到规则配置环节本身条件配置就是所见即所得模式,并不需要对规则结果也同步实时显示出来,因此通过点击按钮主动触发也没问题的。

开源平台资料

平台名称:一二三开发平台
简介: 企业级通用开发平台
设计资料:[csdn专栏]
开源地址:[Gitee]
开源协议:MIT
如果您在阅读本文时获得了帮助或受到了启发,希望您能够喜欢并收藏这篇文章,为它点赞~
请在评论区与我分享您的想法和心得,一起交流学习,不断进步,遇见更加优秀的自己!

  • 7
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

学海无涯,行者无疆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值