当前位置: 首页 > article >正文

一二三应用开发平台自定义查询设计与实现系列3——通用化重构

通用化重构

前面我们以一个实体为目标对象,完成了功能开发与调试。

在此基础上,我们对功能进行重构,使其成为平台的标准化、通用化的功能。

前端重构

首先,先把自定义组件挪到了平台公共组件目录下,如下:

然后将列表页面list.vue中原本写死的地方进行改造,原实现如下:

    // 打开自定义查询对话框
    customQuery() {
      //TODO 更换为动态变量
      this.$refs.customQuery.init('Template')
    }

平台原本的实体配置会统一输出当前的实体类型编码,不过遵循的是小驼峰命名,如下:

在工具类增加一个首字母转大写的方法,转换下就能实现通用化,如下:

    // 打开自定义查询对话框
    customQuery() {  
      this.$refs.customQuery.init(this.$StringUtil.capitalizeFirstLetter(this.entityType))
    }

完成上面工作,使用到自定义查询的列表页面list.vue,还是需要引入自定义查询组件。既然是通用标准化功能了,那就可以将其放到mixin中统一处理了,将自定义查询相关功能迁移到listMixin.js中,如下:

经过上述迁移改造后,各实体的列表页面还剩下两部分,功能按钮和页面定义,如下:

调整列表视图list.vue的代码模板,将自定义查询功能默认输出,让用户多一种选择,如某个实体确定不需要该功能,开发人员可以人工移除,删两行代码,1分钟内就能完成。

后续可以调整平台实体配置功能,将是否启用自定义查询功能变为可配置项,并通过代码模板根据配置项输出或不输出查询按钮和自定义查询组件。

此外,还有一个小地方需要修改,把自定义查询的api,加入到公共方法常量中去,如下:

后端重构

后端重构实际简单的多,复杂的查询转换都是公共方法类,需要在controller的代码模板中增加自定义查询的方法即可,如下:

    //region 扩展操作
    /**
    * 自定义查询
    */
    @PostMapping("/customQuery")
    @SystemLog(value = "${table.comment!}-自定义查询")
    @PreAuthorize("hasPermission(null,'${package.ModuleName}:${entity?uncap_first}:query')")
    public ResponseEntity<Result> customQuery(@RequestBody String customQueryString, PageInfo pageInfo, SortInfo sortInfo) {
        // 构造分页对象
        IPage<${entity}> page = new Page<${entity}>(pageInfo.getPageNum(), pageInfo.getPageSize());
        // 构造查询条件
        QueryWrapper<${entity}> queryWrapper = CustomQueryGenerator.generateQueryWrapper(${entity}.class, customQueryString, sortInfo);


        // 查询数据
        ${entity?uncap_first}Service.page(page, queryWrapper);
        // 转换vo
        IPage<${entity}VO> pageVO = mapperFacade.map(page, IPage.class);
        List<${entity}VO> ${entity?uncap_first}VOList=convert2VO(page.getRecords());
        pageVO.setRecords(${entity?uncap_first}VOList);
        return ResultUtil.success(pageVO);
     }

    //endregion

此外,需要将原先放在实体配置entityconfig模块下的工具类CustomQueryGenerator移动到平台最底层的通用模块platform-common下,以便上层模块使用(若放在entityconfig,受依赖关系限制,系统管理下的实体如用户,就无法使用该工具类),如下:

同理,还有三个与筛选器组件相关的vo对象,也需要移动到platform-common模块下,如下:

功能测试

使用系统管理模块(system)下的用户实体作为测试,生成代码如下:

/**
    * 自定义查询
    */
    @PostMapping("/customQuery")
    @SystemLog(value = "用户-自定义查询")
    @PreAuthorize("hasPermission(null,'system:user:query')")
    public ResponseEntity<Result> customQuery(@RequestBody String customQueryString, PageInfo pageInfo, SortInfo sortInfo) {
        // 构造分页对象
        IPage<User> page = new Page<User>(pageInfo.getPageNum(), pageInfo.getPageSize());
        // 构造查询条件
        QueryWrapper<User> queryWrapper = CustomQueryGenerator.generateQueryWrapper(User.class, customQueryString, sortInfo);


        // 查询数据
         userService.page(page, queryWrapper);
        // 转换vo
        IPage<UserVO> pageVO = mapperFacade.map(page, IPage.class);
        List<UserVO> userVOList=convert2VO(page.getRecords());
        pageVO.setRecords(userVOList);
        return ResultUtil.success(pageVO);
     }

在前端拷贝自定义查询按钮及自定义查询页面,运行如下:

整体无报错,但是发现BUG,查询方案的下拉列表显示的不仅仅是用户实体下的方案,连“模板”实体下的方案也显示出来了,推测是没加实体类型进行过滤,接下来修复该BUG。

BUG修复

修改查询方案的下拉列表,增加entityModelCode属性,监听该属性,如不为空则触发数据加载,如下:

<template>
  <el-select
    v-model="selectedValue"
    :size="size"
    clearable
    :disabled="readonly"
    style="width: 200px; margin: 20 auto"
    @change="change"
  >
    <el-option
      v-for="item in dictionaryItemList"
      :key="item.id"
      :value="item.id"
      :label="item.name"
    />
  </el-select>

</template>

<script>
export default {
  name: 'QueryPlanSelect',
  label: '查询方案下拉',
  props: {
    modelValue: {
      type: String,
      required: false,
      default: ''
    },
    code: {
      type: String,
      default: ''
    },
    readonly: {
      type: Boolean,
      required: false,
      default: false
    },
    size: {
      type: String,
      default: ''
    },
    entityModelCode: {
      type: String,
      default: ''
    }
  },
  data() {
    return {
      dictionaryItemList: [],
      selectedValue: ''
    }
  },
  watch: {
    modelValue: {
      immediate: true,
      handler: 'setSelected'
    },
    entityModelCode: {
      immediate: true,
      handler: 'loadData'
    }
  },
  methods: {
    change(value) {
      let rowData = null
      this.dictionaryItemList.forEach((item) => {
        if (item.id === value) {
          rowData = item
          return
        }
      })
      // 更新绑定值
      this.$emit('update:modelValue', value)
      // 注意,此处若命令为change,则可能会与底层实现冲突,导致执行两次
      this.$emit('my-change', value, rowData)
    },
    setSelected() {
      this.selectedValue = this.modelValue
    },
    loadData() {
      if (this.entityModelCode) {
        this.dictionaryItemList = []
        this.$api.system.queryPlan.list({ entityModelCode: this.entityModelCode }).then((res) => {
          this.dictionaryItemList = res.data
          if (this.dictionaryItemList.length == 1) {
            this.selectedValue = this.dictionaryItemList[0].id
            this.$emit('my-change', this.dictionaryItemList[0].id, this.dictionaryItemList[0])
          } else {
            this.selectedValue = ''
            this.$emit('my-change', '', null)
          }
        })
      }
    }
  }
}
</script>

然后在自定义查询页面中,将模型编码绑定到查询方案下拉组件的属性上,如下:

        <QueryPlanSelect
          @my-change="queryPlanChanged"
          :entity-model-code="entityModelCode"
          ref="queryPlanSelect"
          style="margin: auto 20px"
        ></QueryPlanSelect>

完成上述调整后,获取查询方案时就可以区分不同的实体了。

开源平台资料

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


http://www.kler.cn/a/380296.html

相关文章:

  • vue2和vue3在html中引用组件component方式不一样
  • Spring Boot 配置文件启动加载顺序
  • 2024江苏省网络建设与运维省赛Linux(十) mariadb 服务
  • CODESYS可视化星三角降压启动程序控制电气动画图
  • 04字符串算法/代码随想录
  • lost+found目录实现文件找回的原理
  • linux mysql8大小写敏感问题
  • Spring Boot框架在信息学科平台开发中的高级应用
  • SpringBoot在线教育系统:集成第三方服务
  • AWTK文件系统适配器更新-支持RT-Thread DFS POSIX接口
  • Java中的线程安全问题(如果想知道Java中有关线程安全问题的基本知识,那么只看这一篇就足够了!)
  • Java项目实战II基于Java+Spring Boot+MySQL的体育馆使用预约平台的设计与实现(源码+数据库+文档)
  • flask websocket服务搭建,flask-sock 和 flask-socketio
  • 开源 AI 智能名片 2+1 链动模式 S2B2C 商城小程序与私域流量圈层
  • qt QFileInfo详解
  • GR2——在大规模视频数据集上预训练且机器人数据上微调,随后预测动作轨迹和视频(含GR1详解)
  • 【Linux系列】Linux 和 Unix 系统中的`set`命令与错误处理
  • Qt Modbus 2 通信实现
  • Ubuntu桌面环境下没有网络配置图标,只有显示VPN设置
  • 网络:IP分片和组装
  • 考取无人机“飞手”执照,进入部队、电力、铁路、石油企业抢占优势
  • 前端Nginx的安装与应用
  • 电脑如何不断网切换IP:实用方法与注意事项‌
  • Android -- [SelfView] 自定义圆盘指针时钟
  • qt QStatusBar详解
  • k8s 查看cpu使用率最高的pod