WebApp【公共组件库】@前端(For Git Submodule)
Tevin
2021-03-31 e72677f19b20b3b5e51de881078861e972e717e0
列表页筛选组件,第一部分
4 files added
279 ■■■■■ changed files
plugins/filter/CFilter.vue 94 ●●●●● patch | view | raw | blame | history
plugins/filter/CFilterSelect.vue 72 ●●●●● patch | view | raw | blame | history
plugins/filter/cFilter.scss 103 ●●●●● patch | view | raw | blame | history
plugins/filter/index.js 10 ●●●●● patch | view | raw | blame | history
plugins/filter/CFilter.vue
New file
@@ -0,0 +1,94 @@
/**
 * CFilter - 页面筛选
 * @author Tevin
 */
<template>
    <view class="c-filter">
        <view
            class="c-filter-bar"
            v-if="bar"
        >
            <CFilterSelect
                v-if="!bar.type || bar.type==='select'"
                type="bar"
                :label="bar.label"
                :options="bar.options"
                :onChange="evt=>handleChange(bar.name, evt)"
            />
        </view>
        <view
            class="c-filter-more"
            v-if="items && items.length > 0"
            @tap="evt => drawerShow=true"
        >更多筛选 »</view>
        <AtDrawer
            class="c-filter-drawer"
            mask
            right
            :show="drawerShow"
            :onClose="evt => drawerShow=false"
        >
            <scroll-view
                class="c-filter-drawer-list"
                :scrollY="true"
            >
                <view
                    class="box"
                    v-for="(item,index) of items"
                    :key="index"
                >
                    <CFilterSelect
                        v-if="!item.type || item.type==='select'"
                        type="item"
                        :label="item.label"
                        :options="item.options"
                        :onChange="evt=>handleChange(item.name, evt)"
                    />
                </view>
            </scroll-view>
            <view class="c-filter-drawer-btn">
                重置 完成
            </view>
        </AtDrawer>
    </view>
</template>
<script>
import Taro from '@tarojs/taro';
import { AtDrawer } from 'taro-ui-vue';
import CFilterSelect from './CFilterSelect';
import './cFilter.scss';
export default {
    name: 'CFilter',
    components: {
        AtDrawer,
        CFilterSelect,
    },
    props: {
        // 筛选横条
        bar: Object,
        // 展开层筛选项目列表
        items: Array,
        // 筛选变化时的回调
        onChange: Function,
    },
    data() {
        return {
            filters: {},
            drawerShow: false,
        };
    },
    methods: {
        handleChange(name, value) {
            if (typeof value === 'undefined') {
                delete this.filters[name];
            } else {
                this.filters[name] = value;
            }
            this.onChange(this.filters);
        },
    },
};
</script>
plugins/filter/CFilterSelect.vue
New file
@@ -0,0 +1,72 @@
/**
 * CFilterSelect - 筛选项目,单项选择
 * @author Tevin
 */
<template>
    <view
        class="c-filter-select"
        :class="'type-'+type"
    >
        <view
            class="label"
            v-if="type==='item'"
        >{{label}}</view>
        <picker
            mode="selector"
            range-key="name"
            :range="options2"
            @change="evt=>handleChange(evt.detail.value)"
        >
            <view class="content">
                <view
                    class="label"
                    v-if="type==='bar'"
                >
                    {{label}}:
                </view>
                <view :class="selected ? 'value':'empty'">
                    {{selected ? options2[selectIndex].name : ('请选择' + label)}}
                </view>
                <view class='at-icon at-icon-chevron-down' />
            </view>
        </picker>
    </view>
</template>
<script>
import Taro from '@tarojs/taro';
export default {
    name: 'CFilterSelect',
    props: {
        type: String,
        label: String,
        options: Array,
        onChange: Function,
    },
    data() {
        return {
            selectIndex: 0,
            selected: false,
        };
    },
    computed: {
        options2() {
            return [{ name: '- 取消选择 -' }, ...this.options];
        },
    },
    methods: {
        handleChange(index) {
            this.selectIndex = Number(index);
            if (this.selectIndex > 0) {
                this.selected = true;
                this.onChange(this.options2[this.selectIndex].value);
            } else {
                this.selected = false;
                this.onChange();
            }
        },
    },
};
</script>
plugins/filter/cFilter.scss
New file
@@ -0,0 +1,103 @@
/**
 * filter
 * @author Tevin
 */
@import "../../common/sassMixin";
.c-filter {
    width: 100%;
    height: 86px;
    line-height: 86px;
    font-size: 30px;
    color: #666;
    background-color: #fff;
    border-top: 1px solid #eee;
    .c-filter-bar {
        float: left;
        width: 550px;
        height: 100%;
        padding: 0 20px;
        box-sizing: border-box;
    }
    .c-filter-more {
        float: right;
        width: 200px;
        height: 100%;
        box-sizing: border-box;
        text-align: center;
        border-left: 1PX solid #d6e4ef;
        transition: background-color .3s;
        &:active {
            background-color: #f2f2f2;
        }
    }
    .c-filter-drawer {
        .at-drawer__content {
            width: 550px;
        }
        .c-filter-drawer-list {
            height: calc(100% - 90px);
            border-top: 1PX solid #eee;
            .box {
                min-height: 20px;
                padding: 30px 0 10px 30px;
                border-bottom: 1PX solid #eee;
            }
        }
        .c-filter-drawer-btn {
            height: 90px;
        }
    }
}
.c-filter-select {
    .content {
        @include flexbox(flex, flex-start center);
        white-space: nowrap;
        .empty,
        .value {
            display: inline-block;
            vertical-align: middle;
            @include ellipsis();
        }
        .empty {
            color: #ccc;
        }
        .value {
            color: #6190e8;
        }
        .at-icon {
            text-align: center;
            color: #666;
        }
    }
    &.type-bar {
        .content {
            height: 86px;
            line-height: 1;
            .label {
                color: #666;
            }
            .at-icon {
                vertical-align: middle;
            }
        }
    }
    &.type-item {
        .label {
            font-weight: bold;
            color: #666;
            line-height: 35px;
        }
        .content {
            .empty,
            .value {
                flex: 6;
            }
            .at-icon {
                flex: 1;
            }
        }
    }
}
plugins/filter/index.js
New file
@@ -0,0 +1,10 @@
/**
 * filters
 * @author Tevin
 */
import CFilter from '@components/plugins/filter/CFilter.vue';
export {
    CFilter
}