From 2c8603596c79d104e4189a06eb796a8699e25140 Mon Sep 17 00:00:00 2001
From: Tevin <tingquanren@163.com>
Date: Thu, 16 May 2024 17:08:33 +0800
Subject: [PATCH] 列表筛选器组件,调整数据传递格式,横条完整支持输入框

---
 plugins/filter/cFilterInput.scss    |   38 ++++---
 plugins/filter/CFilterDateRange.vue |   28 +++-
 plugins/filter/CFilterInput.vue     |   56 +++++++++--
 plugins/filter/CFilterSelect.vue    |   34 ++++--
 plugins/filter/CFilterRadio.vue     |   21 +++-
 plugins/filter/CFilter.vue          |   92 ++++++++++--------
 6 files changed, 176 insertions(+), 93 deletions(-)

diff --git a/plugins/filter/CFilter.vue b/plugins/filter/CFilter.vue
index c5b610a..2517699 100644
--- a/plugins/filter/CFilter.vue
+++ b/plugins/filter/CFilter.vue
@@ -8,32 +8,32 @@
         class="c-filter"
         ref="filter"
     >
-        <view
-            class="c-filter-bar"
-            v-if="bar"
-        >
+        <view class="c-filter-bar">
             <CFilterSelect
                 v-if="bar.type === 'select'"
-                type="bar"
+                place="bar"
                 :label="bar.label"
+                :name="bar.name"
                 :options="selectOptions[bar.name] || []"
                 :cancelable="bar.cancelable"
                 :value="filterRes[bar.name]"
-                :onChange="evt => handleBarChange(bar.name, evt)"
+                :onChange="evt => handleChange(evt)"
             />
             <CFilterDateRange
-                v-if="bar.type === 'dateRange'"
-                type="bar"
+                v-else-if="bar.type === 'dateRange'"
+                place="bar"
+                :name="bar.name"
                 :label="bar.label"
                 :value="filterRes[bar.name]"
-                :onChange="evt => handleBarChange(bar.name, evt)"
+                :onChange="evt => handleChange(evt)"
             />
             <CFilterInput
-                v-if="bar.type === 'input'"
-                type="bar"
+                v-else-if="bar.type === 'input'"
+                place="bar"
+                :name="bar.name"
                 :label="bar.label"
                 :value="filterRes[bar.name]"
-                :onChange="evt => handleItemChange(bar.name, evt)"
+                :onChange="evt => handleChange(evt)"
             />
         </view>
         <view
@@ -61,33 +61,37 @@
                 >
                     <CFilterSelect
                         v-if="item.type === 'select'"
-                        type="item"
+                        place="item"
                         :label="item.label"
+                        :name="item.name"
                         :options="selectOptions[item.name] || []"
                         :value="filterRes[item.name]"
-                        :onChange="evt => handleItemChange(item.name, evt)"
+                        :onChange="evt => handleChange(evt)"
                     />
                     <CFilterDateRange
-                        v-if="item.type === 'dateRange'"
-                        type="item"
+                        v-else-if="item.type === 'dateRange'"
+                        place="item"
                         :label="item.label"
+                        :name="item.name"
                         :value="filterRes[item.name]"
-                        :onChange="evt => handleItemChange(item.name, evt)"
+                        :onChange="evt => handleChange(evt)"
                     />
                     <CFilterRadio
-                        v-if="item.type === 'radio'"
-                        type="item"
+                        v-else-if="item.type === 'radio'"
+                        place="item"
                         :label="item.label"
+                        :name="item.name"
                         :options="selectOptions[item.name] || []"
                         :value="filterRes[item.name]"
-                        :onChange="evt => handleItemChange(item.name, evt)"
+                        :onChange="evt => handleChange(evt)"
                     />
                     <CFilterInput
-                        v-if="item.type === 'input'"
-                        type="item"
+                        v-else-if="item.type === 'input'"
+                        place="item"
                         :label="item.label"
+                        :name="item.name"
                         :value="filterRes[item.name]"
-                        :onChange="evt => handleItemChange(item.name, evt)"
+                        :onChange="evt => handleChange(evt)"
                     />
                 </view>
             </scroll-view>
@@ -155,27 +159,31 @@
         handleOpen() {
             this.drawerShow = true;
         },
-        handleBarChange(name, value) {
-            this.$set(this.filterRes, name, value);
-            this.onChange(this.filterRes);
-        },
-        handleItemChange(name, value) {
-            this.$set(this.filterRes, name, value);
-            this.itemsChanged = true;
-            // 如果变化值不为空
-            if (typeof value !== 'undefined') {
-                this.itemsFilled = true;
+        handleChange(changed) {
+            // 横条项
+            if (changed.place === 'bar') {
+                this.$set(this.filterRes, changed.name, changed.value);
+                this.onChange(this.filterRes);
             }
-            // 为空是检查所有面板值是否为空
-            else {
-                let valuehas = false;
-                for (let item of this.items) {
-                    if (typeof this.filterRes[item.name] !== 'undefined') {
-                        valuehas = true;
-                        break;
-                    }
+            // 展开项
+            else if (changed.place === 'item') {
+                this.$set(this.filterRes, changed.name, changed.value);
+                this.itemsChanged = true;
+                // 如果变化值不为空
+                if (typeof value !== 'undefined') {
+                    this.itemsFilled = true;
                 }
-                this.itemsFilled = valuehas;
+                // 为空时检查所有面板值是否为空
+                else {
+                    let valuehas = false;
+                    for (let item of this.items) {
+                        if (typeof this.filterRes[item.name] !== 'undefined') {
+                            valuehas = true;
+                            break;
+                        }
+                    }
+                    this.itemsFilled = valuehas;
+                }
             }
         },
         handleClean() {
diff --git a/plugins/filter/CFilterDateRange.vue b/plugins/filter/CFilterDateRange.vue
index d2fb0d7..2893e0e 100644
--- a/plugins/filter/CFilterDateRange.vue
+++ b/plugins/filter/CFilterDateRange.vue
@@ -6,22 +6,22 @@
 <template>
     <view
         class="c-filter-select"
-        :class="'type-'+type"
+        :class="'type-'+place"
     >
         <view
             class="label"
-            v-if="type==='item'"
+            v-if="place==='item'"
         >{{label}}</view>
         <CDateRangeAction
             :value="value"
-            :onChange="evt=>handleChange(evt)"
+            :onChange="evt => handleChange(evt)"
         >
             <view class="content">
                 <view
                     class="label"
-                    v-if="type==='bar'"
-                >{{label}}:</view>
-                <view :class="selected ? 'filled':'empty'">
+                    v-if="place==='bar'"
+                >{{label}}</view>
+                <view :class="selected?'filled':'empty'">
                     {{selected ? value.replace(',', ' , ') : ('请选择' + label)}}
                 </view>
                 <view class="at-icon at-icon-chevron-down" />
@@ -40,9 +40,15 @@
         CDateRangeAction,
     },
     props: {
-        type: String,
+        // 位置类型,bar、item
+        place: String,
+        // 项名称
         label: String,
-        value: null,
+        // 项键名
+        name: String,
+        // 项值
+        value: String,
+        // 变化回调
         onChange: Function,
     },
     data() {
@@ -55,7 +61,11 @@
     },
     methods: {
         handleChange(dateRange) {
-            this.onChange(dateRange);
+            this.onChange({
+                place: this.place,
+                name: this.name,
+                value: dateRange,
+            });
         },
     },
 };
diff --git a/plugins/filter/CFilterInput.vue b/plugins/filter/CFilterInput.vue
index e03c129..ab44979 100644
--- a/plugins/filter/CFilterInput.vue
+++ b/plugins/filter/CFilterInput.vue
@@ -6,14 +6,17 @@
 <template>
     <view
         class="c-filter-input"
-        :class="'type-'+type"
+        :class="['type-'+place, focusing?'':'off']"
     >
         <view class="label">{{label}}</view>
-        <AtInput
+        <input
+            class="input"
             type="text"
             :placeholder="'请输入' + label"
             :value="value"
-            :onChange="evt => handleChange(evt)"
+            @input="evt => handleChange(evt.target.value)"
+            @focus="evt => handleFocus()"
+            @blur="evt => handleBlur(evt.target.value)"
         />
     </view>
 </template>
@@ -29,23 +32,56 @@
         AtInput,
     },
     props: {
-        type: String,
+        // 位置类型,bar、item
+        place: String,
+        // 项名称
         label: String,
+        // 项键名
+        name: String,
+        // 项值
         value: String,
+        // 变化回调
         onChange: Function,
     },
     data() {
-        return {};
+        return {
+            focusing: false,
+        };
     },
     methods: {
         handleChange(value) {
-            if (value) {
-                this.onChange(value);
-            } else {
-                this.onChange(undefined);
+            // 横条时,不响应变化
+            if (this.place === 'bar') {
+                return;
             }
+            this.onChange({
+                place: this.place,
+                name: this.name,
+                value: value || undefined,
+            });
+        },
+        handleFocus() {
+            this.focusing = true;
+        },
+        handleBlur(value, act) {
+            this.focusing = !!value;
+            // 展开项时,不响应失去焦点
+            if (this.place === 'item') {
+                return;
+            }
+            // 未改变值时,不触发
+            if (this.value === value) {
+                return;
+            }
+            this.onChange({
+                place: this.place,
+                name: this.name,
+                value: value || undefined,
+            });
         },
     },
-    mounted() {},
+    mounted() {
+        this.focusing = !!this.value;
+    },
 };
 </script>
\ No newline at end of file
diff --git a/plugins/filter/CFilterRadio.vue b/plugins/filter/CFilterRadio.vue
index f4489ec..ef7ea67 100644
--- a/plugins/filter/CFilterRadio.vue
+++ b/plugins/filter/CFilterRadio.vue
@@ -6,11 +6,11 @@
 <template>
     <view
         class="c-filter-radio"
-        :class="'type-'+type"
+        :class="'type-'+place"
     >
         <view
             class="label"
-            v-if="type==='item'"
+            v-if="place==='item'"
         >{{label}}</view>
         <view class="content">
             <view
@@ -21,7 +21,7 @@
             >
                 <view
                     class="c-filter-radio-icon"
-                    :class="value === item.value ? 'checked' : ''"
+                    :class="value===item.value?'checked':''"
                 >
                     <AtIcon value="check" />
                 </view>
@@ -42,10 +42,17 @@
         AtIcon,
     },
     props: {
-        type: String,
+        // 位置类型,bar、item
+        place: String,
+        // 项名称
         label: String,
+        // 项键名
+        name: String,
+        // 选项
         options: Array,
+        // 项值
         value: [String, Number],
+        // 变化回调
         onChange: Function,
     },
     data() {
@@ -53,7 +60,11 @@
     },
     methods: {
         handleChange(value) {
-            this.onChange(value);
+            this.onChange({
+                place: this.place,
+                name: this.name,
+                value,
+            });
         },
     },
 };
diff --git a/plugins/filter/CFilterSelect.vue b/plugins/filter/CFilterSelect.vue
index 1c04022..d46736d 100644
--- a/plugins/filter/CFilterSelect.vue
+++ b/plugins/filter/CFilterSelect.vue
@@ -6,25 +6,25 @@
 <template>
     <view
         class="c-filter-select"
-        :class="'type-'+type"
+        :class="'type-'+place"
     >
         <view
             class="label"
-            v-if="type==='item'"
+            v-if="place==='item'"
         >{{label}}</view>
         <picker
             mode="selector"
             range-key="name"
             :range="options2"
             :value="current"
-            @change="evt=>handleChange(evt.detail.value)"
+            @change="evt => handleChange(evt.detail.value)"
         >
             <view class="content">
                 <view
                     class="label"
-                    v-if="type==='bar'"
-                >{{label}}:</view>
-                <view :class="selected ? 'filled':'empty'">
+                    v-if="place==='bar'"
+                >{{label}}</view>
+                <view :class="selected?'filled':'empty'">
                     {{selected ? options2[current].name : ('请选择' + label)}}
                 </view>
                 <view class="at-icon at-icon-chevron-down" />
@@ -40,17 +40,25 @@
 export default {
     name: 'CFilterSelect',
     props: {
-        type: String,
+        // 位置类型,bar、item
+        place: String,
+        // 项名称
         label: String,
+        // 项键名
+        name: String,
+        // 选项
         options: {
             type: Array,
             default: () => [],
         },
+        // 是否额外显示【取消选择】的项
         cancelable: {
             type: Boolean,
             default: true,
         },
-        value: null,
+        // 项值
+        value: [Number, String],
+        // 变化回调
         onChange: Function,
     },
     data() {
@@ -87,14 +95,20 @@
     methods: {
         handleChange(index) {
             const selectIndex = Number(index);
+            const selectItem = this.options2[selectIndex];
+            const changed = {
+                place: this.place,
+                name: this.name,
+                value: selectItem.value || selectItem.id,
+            };
             if (this.cancelable) {
                 if (selectIndex > 0) {
-                    this.onChange(this.options2[selectIndex].value);
+                    this.onChange(changed);
                 } else {
                     this.onChange();
                 }
             } else {
-                this.onChange(this.options2[selectIndex].value);
+                this.onChange(changed);
             }
         },
     },
diff --git a/plugins/filter/cFilterInput.scss b/plugins/filter/cFilterInput.scss
index 48015a8..ff73112 100644
--- a/plugins/filter/cFilterInput.scss
+++ b/plugins/filter/cFilterInput.scss
@@ -6,27 +6,31 @@
 @import "../../common/sassMixin";
 
 .c-filter-input {
-    .label {
-        line-height: 40px;
-    }
-    .at-input {
-        height: 90px;
-        padding: 0;
-        margin: 0;
-        background-color: transparent;
-        &::after {
-            display: none;
-        }
-        input {
-            height: 90px;
-            line-height: 90px;
-        }
+    &.off .input {
+        opacity: 0.5;
     }
     &.type-bar {
         display: flex;
+        height: 90px;
         align-items: center;
-        .at-input {
-            margin-left: 14px;
+        .label {
+            line-height: 90px;
+            padding-right: 12px;
+        }
+        .input {
+            flex: 1;
+            height: 90px;
+            line-height: 90px;
+            color: #6190e8;
+        }
+    }
+    &.type-item {
+        .label {
+            line-height: 40px;
+        }
+        .input {
+            height: 100px;
+            line-height: 100px;
         }
     }
 }
\ No newline at end of file

--
Gitblit v1.9.1