需求:可以動態增減組合條件來進行資料查詢。
介面執行效果如下圖所示:
介面第一次載入時,預設會顯示一個空的查詢條件,如下圖所示:
點選“加”圖示,可以無限增加查詢條件,也可以點選“減”圖示刪除新增的查詢條件,如下圖所示:
說明:第一個下拉框的資料變化時,第三個下拉框的資料要進行聯動,第三個元件可以是下拉框也可以是文字框,它是根據第一個下拉框的資料來決定的。第二個下拉框是固定的四個選項>、<、=、!=。如下圖所示:
定義資料結構:
{ "data": { "array": [{ "opts": [{ "val": "0", "name": "停止" }, { "val": "1", "name": "執行" }], "paramCode": "runStatus", "name": "執行狀態" }, { "opts": [{ "val": "0", "name": "否" }, { "val": "1", "name": "是" }], "paramCode": "alarmStatus", "name": "報警與否" }, { "opts": [{ "val": "0", "name": "就地" }, { "val": "1", "name": "遠端" }], "paramCode": "remoteLocal", "name": "遠端就地" }, { "opts": [{ "val": 0, "name": "禁用" }, { "val": 1, "name": "啟用" }], "paramCode": "startUse", "name": "是否啟用" }, { "opts": [{ "val": "0", "name": "變頻" }, { "val": "1", "name": "工頻" }], "paramCode": "runMode", "name": "工頻啟停" }, { "opts": [{ "val": 0, "name": "手動" }, { "val": 1, "name": "自動" }], "paramCode": "controlMode", "name": "控制模式" }, { "opts": [{ "val": "0", "name": "手動" }, { "val": "1", "name": "自動" }], "paramCode": "frequencyMode", "name": "頻率手自動" }, { "opts": [], "paramCode": "frequencySetValue", "name": "頻率設定" }, { "opts": [], "paramCode": "frequencyReturnValue", "name": "頻率反饋" }, { "opts": [], "paramCode": "tempSetValue", "name": "溫度設定" }, { "opts": [], "paramCode": "tempReturnValue", "name": "溫度反饋" }, { "opts": [{ "val": 0, "name": "關" }, { "val": 1, "name": "開" }], "paramCode": "newWindValveOnOff", "name": "新風閥啟停" }, { "opts": [], "paramCode": "newWindValveOpen", "name": "新風閥開度" }, { "opts": [], "paramCode": "newWindTemp", "name": "新風閥溫度" }, { "opts": [], "paramCode": "newWindHumidity", "name": "新風閥溼度" }, { "opts": [{ "val": 0, "name": "關" }, { "val": 1, "name": "開" }], "paramCode": "returnWindValveOnOff", "name": "迴風閥啟停" }, { "opts": [], "paramCode": "returnWindValveOpen", "name": "迴風閥開度" }, { "opts": [], "paramCode": "returnWindHumidity", "name": "迴風閥溼度" }, { "opts": [], "paramCode": "co2", "name": "迴風閥co2" }, { "opts": [{ "val": "0", "name": "手動" }, { "val": "1", "name": "自動" }], "paramCode": "waterValveHandAuto", "name": "水閥手自動" }, { "opts": [{ "val": 0, "name": "關" }, { "val": 1, "name": "開" }], "paramCode": "waterValveOnOff", "name": "水閥啟停" }, { "opts": [], "paramCode": "waterValveOpenSet", "name": "水閥開度設定" }, { "opts": [], "paramCode": "waterValveOpenReturn", "name": "水閥開度反饋" }, { "opts": [], "paramCode": "supplyAirTemp", "name": "送風溫度" }, { "opts": [], "paramCode": "supplyAirHumidity", "name": "送風溼度" }, { "opts": [], "paramCode": "supplyAirPressure", "name": "送風靜壓" }, { "opts": [{ "val": 0, "name": "關" }, { "val": 1, "name": "開" }], "paramCode": "humidityValveOnOff", "name": "加溼閥啟停" }, { "opts": [], "paramCode": "humidityValveOpen", "name": "加溼閥開度" }, { "opts": [], "paramCode": "filterDiffPressure", "name": "過濾網壓差" }, { "opts": [{ "val": 0, "name": "關" }, { "val": 1, "name": "開" }], "paramCode": "elecHeatOnOff", "name": "電加熱" }, { "opts": [], "paramCode": "power", "name": "功率" }, { "opts": [], "paramCode": "runTime", "name": "執行時間" }, { "opts": [], "paramCode": "loadPower", "name": "供冷負荷" }, { "opts": [], "paramCode": "cold", "name": "累計供冷量" }, { "opts": [{ "val": 0, "name": "正常" }, { "val": 1, "name": "中斷" }], "paramCode": "commuInterrupt", "name": "通訊是否正常" }] }, "code": 200, "msg": "", "errors": null }
因為資料量不大,為了提升效能,資料是介面一次性返回的,資料的聯動是在記憶體當中進行資料篩選,從而避免頻繁的介面呼叫。
在資料結構當中,當opts屬性值為空陣列時,第三個元件顯示為文字框,否則顯示為下拉框,並把opts中的資料作為第三個元件的下拉框內容展示出來。當第三個元件是下拉框時,第二個下拉框只能顯示=和!=這兩項,如果是文字框時,都可以顯示。
後端介面需要的查詢引數是:
dataListParams: [{paramName: "runStatus", operator: 2, value: "0"}, {paramName: "startUse", operator: 2, value: 0}]
接下來,我們定義vue元件中的內容,Dom部分:
<div class='search-item'> <label>組合條件:</label> </div> <div class="search-item" v-for="(paramObj,index) in dataListParams" :key="index"> <!-- 引數名 --> <el-select v-model="paramObj.paramName" filterable clearable @change="(e)=>changeParam(e,index)" placeholder="請選擇" style="width:100px"> <el-option v-for="item in paramList" :key="item.paramCode" :label="item.name" :value="item.paramCode"></el-option> </el-select> <!-- 操作符列表 --> <el-select v-model="paramObj.operator" clearable placeholder="" style="width:60px"> <el-option v-for="(item,sindex) in operatorOptions" :disabled="getDisabled(sindex,index)" :key="item.id" :label="item.name" :value="item.id"></el-option> </el-select> <!-- 引數值 --> <el-select v-if="listOpts[index].length>0" v-model="paramObj.value" filterable clearable placeholder="請選擇" style="width:100px"> <el-option v-for="item in listOpts[index]" :key="item.val" :label="item.name" :value="item.val"></el-option> </el-select> <el-input v-else v-model="paramObj.value" :clearable="true" placeholder="請輸入" style="width:100px"></el-input> <span v-if="index==0" class="add-where"><i class="iconfont icon-add" @click="addWhere"></i></span> <span v-else class="remove-where"><i class="iconfont icon-shanchu1" @click="removeWhere(index)"></i></span> </div>
js部分:
export default { mixins: [indexOptions], data () { return { //操作符列表 operatorOptions: [ { id: 0, name: '>' }, { id: 1, name: '<' }, { id: 2, name: '=' }, { id: 3, name: '!=' } ], //組合條件 dataListParams: [{ paramName: "", operator: '', value: "" }], deviceIds: [],
paramList:[],//引數列表,包含操作名稱、操作值列表(JSon資料結構)
listOpts: [[]]//操作值列表 } }, computed: {//篩選引數列表,如果引數列表dataListParams當中有任何一個屬性值為空,則不傳遞 filterDataListParams () { return this.dataListParams.filter(f => { return f.paramName !== "" && f.operator !== "" && f.value !== "" }); } }, methods: {//獲取操作選項啟用、禁用 getDisabled (sindex, index) { if (this.listOpts.length > 0 && this.listOpts[index].length > 0) { return [0, 1].includes(sindex); } else { return false; } }, //新增組合條件 addWhere () { this.dataListParams.push({ paramName: '', operator: '', value: '' }); this.listOpts.push([]); }, //移除組合條件 removeWhere (index) { this.dataListParams.splice(index, 1); this.listOpts.splice(index, 1); }, //根據引數編碼獲取操作列表 getOptsByParamCode (code,) { let res = this.paramList.find(f => f.paramCode == code); return res ? res.opts : []; }, //引數選項變化 changeParam (code, index) { //變化之前的型別 let preType = this.listOpts[index].length > 0; //是否下拉框 let arr = this.getOptsByParamCode(code); this.listOpts[index] = arr; this.dataListParams[index].value = ''; //變化之後的型別 let nextType = arr.length > 0;//是否是下拉框 //前後型別不一致時,清空操作符 if (preType != nextType) { this.dataListParams[index].operator = ''; } } } };
當第一個下拉框選項變化時,如果第三個元件是相同型別(下拉框或文字框),則第二個下拉框的選項不清空,否則清空。
只有一組查詢條件當中三個選項的值都不為空時,才會把引數傳遞給後端,所以前端通過計算熟悉filterDataListParams進行了資料過濾。
由於資料結構是動態變化的,所以為了儲存查詢條件的儲存狀態,下拉框的資料列表項也應當是動態的(陣列儲存)。
最後把filterDataListParams作為引數傳遞給後端介面就可以了,這是一個很典型的vue動態資料驅動應用。