文檔驅動 —— 查詢組件:將查詢功能做到極致!你說還有啥沒包含進來?antdv + vue 3.0 全新體驗
- 2020 年 9 月 19 日
- 筆記
- 前端之 —— Vue
源碼
//github.com/naturefwvue/nf-vue3-ant
目的
- 簡單方便,不用寫程式碼就可以實現各種查詢功能
- 把查詢相關的功能都做全,不留遺憾
功能
- 快捷查詢
- 個性化查詢方案
- 可以更換各種查詢方式
- 更多的查詢條件
- meta驅動,無需程式碼
結構
快捷查詢
如上圖,把常用的幾個查詢條件放在第一行,採用緊湊模式,直接放控制項,通過 placeholder 的方式標示控制項是哪個欄位的,這樣在有限的空間裡面可以多放一兩個欄位。
下面可以放功能按鈕(添加等)和數據列表,想要查詢直接點就行,不用點個按鈕,在打開個某某,麻煩。
個性化查詢方案
每個人都可以有自己的查詢習慣,我喜歡(或者工作需要)用這幾個查詢條件,你喜歡那幾個查詢條件,快捷查詢里就那麼幾個位置,到底放哪幾個欄位?
不用掙,我們可以按照自己的需要設置不同的查詢方案,放在快捷裡面,你喜歡就行,不影響別人
更換各種查詢方式
想要用訂單編號查詢,使用模糊查詢還是精確查詢?
精確查詢需要把訂單號都輸入進去,麻煩。
模糊查詢,有可能出現不需要的數據。
以前做項目,遇到訂單號規則升級。老編號五位,新編號十位。用戶想查老訂單,把訂單號都輸入全了,結構還是查到一堆不想要的訂單,因為是模糊查詢。
現在好了,用戶可以自己選擇是模糊查詢還是精確查詢。
數字類型可以選擇等於還是區間查詢,甚至大於、小於這些查詢方式都可以加上。
日期類的查詢,也可以選擇是範圍查詢,還是查詢某一天。
這樣我們做設計的時候就不用糾結,這個欄位到底怎麼查才適合,把可能的查詢方式都給客戶,客戶自己選好了。
更多的查詢條件
有些模組,裡面的欄位非常多,再怎麼個性化設置也不夠用,那麼就需要把全部可以查詢的欄位都拿出來顯示,於是就有了這個全部查詢
多行多列可以多佔
採用<table>的格式的格式,多行多列顯示,這樣更規則一些,更容易對齊。
如果有些控制項比較長,比如時間的範圍查詢、多選組等,那麼可以設置這些長控制項多佔用幾個td,在調整一下先後順序,整個頁面就可以比較好看,不會出現擠的擠死餓的餓死的情況。
這裡「公司名稱」和「公司郵編」佔用兩列(四個td),下面的日期查詢也佔用了兩列(四個td),這樣整體結構比較緊湊,不會有浪費空間的感覺。
meta 驅動
欄位(控制項)需要的屬性都放在meta裡面,做成單獨的json文件,用的時候載入進來就好,所以可以說——實現查詢,再也不用寫程式碼了。
設計思路
根據查詢的特點,封裝下面幾個控制項,順便把查詢方式歸納終結一下。再構思一下查詢數據如何存放的問題。
封裝基礎控制項
基礎控制項要比表單簡單一些,只需要文本、數字、日期、下拉選擇、單選組、多選組這幾個。其實單選組也可以變成下拉選擇的方式,只是想想有時候做成幾個圓圈圈的形式,選擇起來更方便一些。
查詢方式
主要就是等於、不等於、包含、範圍區間這幾種,只是不同的數據類型會有不同的拼接(查詢條件)方式,所以依據不同的數據類型就變成了這麼多。
應該沒有漏掉的了。
查詢控制項本身的屬性
查詢控制項要設置顯示幾列,四列、五列、六列都行,看用戶顯示器有多寬了。
要設置快捷查詢用哪些查詢欄位,還有用戶自己設置的個性化查詢方案。
這些用於生成table
後面的就是每個控制項需要的meta數據了。
程式碼
子控制項,比如文本類
<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>
<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方式是在是要命,當然也可能是我能力有限,反正現在程式碼是看著都頭大,必須重構。
重構之前也可以先看看第一版,以後可以做個對比
<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>
其中生成查詢語句的地方,不用前端操心,因為那是後端的事情,前端只需要提供數據即可,只是我就是後端,所以先在前端拼一下查詢語句。
有點亂,不貼了。
看了看,實在分不出來個數,不知道在這個setup裡面,要如何組織程式碼結構,目前只有一百多行的js程式碼,包括注釋{}等,實際程式碼也就幾十行,我都懷疑我的編程能力了,居然弄的這麼沒法看。
反省中。
改成組件的方式,就可以用data模式了,這樣可看性會高不少。
感想
Ant Design Vue,研究了幾天,感覺有個強大的UI庫,太方便了。其實以前就一直想做這種方式的查詢控制項,但是css很爛,一些效果做不出來,比如抽屜形式的更多查詢條件、查詢方式的切換、個性化方案的選擇等。
日期控制項太複雜了,研究了好幾天還是沒用研究透,還需要繼續專研,因為關於日期時間查詢的地方還有一些細節沒有實現好。
one more thing
後面就是數據列表、分頁。然後一個模組的增刪改查就全了。