前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >文档驱动 —— 查询组件:将查询功能做到极致!你说还有啥没包含进来?antdv + vue 3.0 全新体验 快捷查询个性化查询方案更换各种查询方式更多的查询条件meta 驱动封装基础

文档驱动 —— 查询组件:将查询功能做到极致!你说还有啥没包含进来?antdv + vue 3.0 全新体验 快捷查询个性化查询方案更换各种查询方式更多的查询条件meta 驱动封装基础

作者头像
用户1174620
发布2020-09-21 16:14:03
1.2K0
发布2020-09-21 16:14:03
举报

源码

https://github.com/naturefwvue/nf-vue3-ant

目的

  • 简单方便,不用写代码就可以实现各种查询功能
  • 把查询相关的功能都做全,不留遗憾

功能

  • 快捷查询
  • 个性化查询方案
  • 可以更换各种查询方式
  • 更多的查询条件
  • meta驱动,无需代码

结构

快捷查询

如上图,把常用的几个查询条件放在第一行,采用紧凑模式,直接放控件,通过 placeholder 的方式标示控件是哪个字段的,这样在有限的空间里面可以多放一两个字段。 下面可以放功能按钮(添加等)和数据列表,想要查询直接点就行,不用点个按钮,在打开个某某,麻烦。

个性化查询方案

每个人都可以有自己的查询习惯,我喜欢(或者工作需要)用这几个查询条件,你喜欢那几个查询条件,快捷查询里就那么几个位置,到底放哪几个字段? 不用挣,我们可以按照自己的需要设置不同的查询方案,放在快捷里面,你喜欢就行,不影响别人

更换各种查询方式

想要用订单编号查询,使用模糊查询还是精确查询? 精确查询需要把订单号都输入进去,麻烦。 模糊查询,有可能出现不需要的数据。

以前做项目,遇到订单号规则升级。老编号五位,新编号十位。用户想查老订单,把订单号都输入全了,结构还是查到一堆不想要的订单,因为是模糊查询。

现在好了,用户可以自己选择是模糊查询还是精确查询。

数字类型可以选择等于还是区间查询,甚至大于、小于这些查询方式都可以加上。

日期类的查询,也可以选择是范围查询,还是查询某一天。

这样我们做设计的时候就不用纠结,这个字段到底怎么查才适合,把可能的查询方式都给客户,客户自己选好了。

更多的查询条件

有些模块,里面的字段非常多,再怎么个性化设置也不够用,那么就需要把全部可以查询的字段都拿出来显示,于是就有了这个全部查询

多行多列可以多占

采用<table>的格式的格式,多行多列显示,这样更规则一些,更容易对齐。 如果有些控件比较长,比如时间的范围查询、多选组等,那么可以设置这些长控件多占用几个td,在调整一下先后顺序,整个页面就可以比较好看,不会出现挤的挤死饿的饿死的情况。 这里“公司名称”和“公司邮编”占用两列(四个td),下面的日期查询也占用了两列(四个td),这样整体结构比较紧凑,不会有浪费空间的感觉。

meta 驱动

字段(控件)需要的属性都放在meta里面,做成单独的json文件,用的时候加载进来就好,所以可以说——实现查询,再也不用写代码了。

设计思路

根据查询的特点,封装下面几个控件,顺便把查询方式归纳终结一下。再构思一下查询数据如何存放的问题。

封装基础控件

基础控件要比表单简单一些,只需要文本、数字、日期、下拉选择、单选组、多选组这几个。其实单选组也可以变成下拉选择的方式,只是想想有时候做成几个圆圈圈的形式,选择起来更方便一些。

查询方式

主要就是等于、不等于、包含、范围区间这几种,只是不同的数据类型会有不同的拼接(查询条件)方式,所以依据不同的数据类型就变成了这么多。 应该没有漏掉的了。

查询控件本身的属性

查询控件要设置显示几列,四列、五列、六列都行,看用户显示器有多宽了。 要设置快捷查询用哪些查询字段,还有用户自己设置的个性化查询方案。 这些用于生成table 后面的就是每个控件需要的meta数据了。

代码

子控件,比如文本类

代码语言:javascript
复制
<template>
  <div style="width:160px;" class="components-input-demo-presuffix">
    <a-input
      :id="'id' + meta.controlId"
      :name="'c' + meta.controlId"
      :value="value"
      :placeholder="meta.placeholder"
      :title="meta.title"
      :maxlength="meta.maxlength"
      :autocomplete="meta.autocomplete"
      :key="'ckey_'+meta.controlId"
      size="small"
      @input="myInput"
      >
        <template v-slot:addonBefore>
          <a-dropdown>
            <a class="ant-dropdown-link">{{kind}}</a>
            <template v-slot:overlay>
              <a-menu @click="handleMenuClick">
                <a-menu-item key="401">=</a-menu-item>
                <a-menu-item key="402">≠</a-menu-item>
                <a-menu-item key="403">含</a-menu-item>
              </a-menu>
            </template>
          </a-dropdown>
        </template>
    </a-input>
  </div>
</template>
代码语言:javascript
复制
<script>

export default {
  name: 'nf-find-input',
  model: {
    prop: 'modelValue',
    event: 'input'
  },
  props: {
    modelValue: String,
    meta: {
      type: Object,
      default: () => {
        return {
          controlId: Number, // 编号,区别同一个表单里的其他控件
          colName: String, // 字段名称
          controlType: Number, // 用类型编号表示type
          placeholder: String,
          title: String, // 提示信息
          maxlength: Number, // 最大字符数
          autocomplete: { // off
            type: String,
            default: 'on'
          }
        }
      }
    }
  },
  data () {
    return {
      value: '',
      kind: '含',
      kindkey: '403',
      findKind: {
        401: '=', // 字符串
        402: '≠',
        403: '含',
        404: '不含',
        405: '起始',
        406: '结束',
        411: '=', // 数字
        412: '≠',
        413: '>',
        414: '≥',
        415: '<',
        416: '≤',
        421: '=', // 日期
        422: '≠',
        423: '>',
        424: '≥',
        425: '<',
        426: '≤',
        431: '在',
        432: '在',
        433: '在'
      }
    }
  },
  methods: {
    myInput: function (e) {
      this.value = e.target.value
      this.send()
    },
    handleButtonClick (e) {
      console.log('click left button', e)
    },
    handleMenuClick (e) {
      this.kindkey = e.key
      this.kind = this.findKind[e.key]
      console.log('click', e)
      this.send()
    },
    send: function () {
      var returnValue = []
      returnValue.push(this.kindkey)
      returnValue.push(this.value)
      var colName = this.meta.colName
      this.$emit('update:modelValue', returnValue) // 返回给调用者
      this.$emit('getvalue', returnValue, colName) // 返回给中间组件
    }
  }
}
</script>

这个比表单用的子控件要简单很多。 其他的就不贴了,大同小异。

查询控件

暂时没有做成单独的控件,马上要改了,因为vue3.0的setup方式是在是要命,当然也可能是我能力有限,反正现在代码是看着都头大,必须重构。 重构之前也可以先看看第一版,以后可以做个对比

代码语言:javascript
复制
<template>
  <div class="home">
    <h1>查询演示</h1>
    <div style="background-color:#dddddd;height:600px;width:100px;float:left;">
      <a href="#" @click="myClick('companyFind')">公司信息</a> <br>
      <a href="#" @click="myClick('personFind')">员工信息</a>
    </div>
    <div style="background-color:#eee;height:600px;width:1100px;float:left;">
      <!--快捷查询,一行-->
      <div
        :style="{
          height: '70px',
          overflow: 'hidden',
          position: 'relative',
          border: '1px solid #ebedf0',
          borderRadius: '2px',
          padding: '2px',
          textAlign: 'left',
          background: '#fafafa',
        }"
      >
        <div class="ant-table ant-table-body ant-table-default ant-table-bordered" >
          <table role="all">
            <tbody class="ant-table-tbody">
              <tr>
                <td><!--个性化查询方案-->
                  <a-dropdown size="small">
                    <template v-slot:overlay>
                      <a-menu @click="handleMenuClick">
                        <a-menu-item v-for="(item,key) in findMeta.customer" :key="key">
                          <UserOutlined />{{item.name}}</a-menu-item>
                      </a-menu>
                    </template>
                    <a-button style="margin-left: 8px"> 快捷 <DownOutlined /> </a-button>
                  </a-dropdown>
                </td>
                <template v-for="key in findMeta.quickFind" :key="key">
                  <td align="left" style="padding:3px 3px;height:20px" v-if="!isEnd(tr, td)">
                    <nfInput v-model="modelValue[getMeta2(key).colName]"
                    :meta="findItem[key]" />
                  </td>
                </template>
                <td><a-button type="primary" @click="showDrawer">更多</a-button></td>
              </tr>
            </tbody>
          </table>
        </div>
      </div>
      <!--更多查询条件,用抽屉打开-->
      <a-drawer
        title="更多查询条件"
        placement="top"
        :closable="false"
        :visible="findVisible"
        @close="onClose"
      >
        <div class="ant-table ant-table-body ant-table-default ant-table-bordered" >
          <table role="all">
            <tbody class="ant-table-tbody">
              <template v-for="(tr, index) in findTable" :key="index"><!--循环行-tr-->
                <tr>
                  <template v-for="(td, index2) in tr" :key="index+'-'+index2"><!--循环列-td-->
                    <td align="right" style="padding:3px 3px;height:20px">
                      {{findItem[td].title}}:
                    </td>
                    <td :colspan="findItem[td].tdCount" align="left" style="padding:3px 3px;height:20px">
                      <nfInput v-model="modelValue[getMeta2(td).colName]"
                      :meta="findItem[td]" />
                    </td>
                  </template>
                </tr><!--循环行-tr 结束 -->
              </template>
            </tbody>
          </table>
        </div>
      </a-drawer>
      <!--生成查询语句,这个是不用的-->
      <div align="left" style="padding:100px 15px">
        <span v-for="(item,key,index) in modelValue" :key="index"><!--遍历model-->
          <template v-if="typeof item === 'object'"><!--判断是不是数组-->
            <template v-if="item.length == 2"> <!--判断数组长度-->
              {{key}} {{findWhere[item[0]].replace('{k}',item[1])}} and <br>
            </template>
            <template v-if="item.length == 3"> <!--判断数组长度-->
              {{key}} {{findWhere[item[0]].replace('{k1}',item[1]).replace('{k2}',item[2])}} and <br>
            </template>
          </template>
        </span>
      </div>
    </div>
  </div>
</template>

其中生成查询语句的地方,不用前端操心,因为那是后端的事情,前端只需要提供数据即可,只是我就是后端,所以先在前端拼一下查询语句。

代码语言:javascript
复制
有点乱,不贴了。

看了看,实在分不出来个数,不知道在这个setup里面,要如何组织代码结构,目前只有一百多行的js代码,包括注释{}等,实际代码也就几十行,我都怀疑我的编程能力了,居然弄的这么没法看。 反省中。

改成组件的方式,就可以用data模式了,这样可看性会高不少。

感想

Ant Design Vue,研究了几天,感觉有个强大的UI库,太方便了。其实以前就一直想做这种方式的查询控件,但是css很烂,一些效果做不出来,比如抽屉形式的更多查询条件、查询方式的切换、个性化方案的选择等。 日期控件太复杂了,研究了好几天还是没用研究透,还需要继续专研,因为关于日期时间查询的地方还有一些细节没有实现好。

one more thing

后面就是数据列表、分页。然后一个模块的增删改查就全了。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 源码
  • 目的
  • 功能
  • 结构
    • 快捷查询
      • 个性化查询方案
        • 更换各种查询方式
          • 更多的查询条件
            • 多行多列可以多占
          • meta 驱动
          • 设计思路
            • 封装基础控件
              • 查询方式
                • 查询控件本身的属性
                • 代码
                  • 子控件,比如文本类
                    • 查询控件
                    • 感想
                    • one more thing
                    领券
                    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档