zoukankan      html  css  js  c++  java
  • taro3.x: 查询条件

    tsx:

    import React, { useEffect, useState } from 'react'
    import { View, Text, ScrollView, Image } from '@tarojs/components'
    import classnames from 'classnames'
    import { find, remove } from 'lodash'
    
    import api from '@services/api'
    import app from '@services/request'
    import NavBar from '@components/navbar/index'
    import useNavData from '@hooks/useNavData'
    import { PRICE_TYPE, SALE_STATUS } from '@constants/house'
    import '@styles/common/house-list.scss'
    import '@styles/common/search-tab.scss'
    import './index.scss'
    
    interface IFilter {
        id: string
        name: string
        value?: string
    }
    
    interface IConditionState {
        region?: IFilter
        unit_price?: IFilter
        total_price?: IFilter
        house_type?: IFilter
        house_property?: IFilter
        sale_status?: IFilter
        renovation?: IFilter
        feature?: IFilter
    
    }
    
    const initial_value = { id: '', name: '', value: '' }
    
    const INIT_CONDITION = {
        region: { id: 'all000', name: '不限', value: '' },
        unit_price: { id: 'all000', name: '不限', value: '' },
        total_price: initial_value,
        house_type: { id: 'all000', name: '不限', value: '' },
        house_property: initial_value,
        sale_status: initial_value,
        renovation: initial_value,
        feature: initial_value
    }
    
    const NewHouse = () => {
        const { appHeaderHeight, contentHeight } = useNavData()
        const footerBtnHeight = 60
        const scrollHeight = contentHeight * 0.5 - footerBtnHeight
        const scrollMoreHeight = contentHeight * 0.6 - footerBtnHeight
        const [tab, setTab] = useState<string>('')
        const [priceType, setPriceType] = useState<string>('unit_price')
        const [selected, setSelected] = useState<IConditionState>(INIT_CONDITION)
        const [condition, setCondition] = useState<any>()
        const [houseList, setHouseList] = useState<any>([])
        const tabs = [
            {
                type: 'region',
                name: '区域',
                keys: ['region']
            },
            {
                type: 'price',
                name: '价格',
                keys: ['unit_price', 'total_price']
            },
            {
                type: 'house_type',
                name: '户型',
                keys: ['house_type']
            },
            {
                type: 'more',
                name: '更多',
                keys: ['house_property', 'sale_status', 'renovation', 'feature']
            }]
        const priceTabs = [
            {
                id: 'id_01',
                name: '按单价',
                value: "unit_price"
            },
            {
                id: 'id_02',
                name: '按总价',
                value: "total_price"
            }
        ]
    
        useEffect(() => {
            fetchCondition()
            fetchHouseList()
        }, [])
    
        const fetchCondition = () => {
            app.request({
                url: api.getHouseCondition,
                data: { type: 'newHouse' }
            }, {
                isMock: true,
                loading: false
            }).then((result: any) => {
                setCondition(result || {})
            })
        }
    
        const fetchHouseList = () => {
            app.request({
                url: api.getHouseNew,
                data: {}
            }, {
                isMock: true,
                loading: false
            }).then((result: any) => {
                setHouseList(result || [])
            })
        }
    
        const switchCondition = (item) => {
            if (tab === item.type) {
                setTab('')
                return
            }
            setTab(item.type)
        }
    
        const handleSingleClick = (key: string, item: any) => {
            setTab('')
            if (key === 'unit_price') {
                setSelected({
                    ...selected,
                    total_price: initial_value,
                    [key]: item
                })
            } else if (key === 'total_price') {
                setSelected({
                    ...selected,
                    unit_price: initial_value,
                    [key]: item
                })
            } else {
                setSelected({
                    ...selected,
                    [key]: item
                })
            }
        }
        const handleMultiClick = (key: string, item: any) => {
            let selectedValue = selected[key]
            if (selectedValue instanceof Object) {
                if (selectedValue.id === item.id) {
                    setSelected({
                        ...selected,
                        [key]: initial_value
                    })
                } else {
                    setSelected({
                        ...selected,
                        [key]: item
                    })
                }
            }
    
            if (selectedValue instanceof Array) {
                let target = find(selectedValue, { id: item.id })
                if (target) {
                    remove(selectedValue, { id: item.id })
                    setSelected({
                        ...selected,
                        [key]: selectedValue
                    })
                } else {
                    setSelected({
                        ...selected,
                        [key]: [...selectedValue, item]
                    })
                }
            }
        }
    
        const handleReset = () => {
            setSelected({
                ...selected,
                house_property: initial_value,
                renovation: initial_value,
                sale_status: initial_value,
                feature: initial_value
            })
        }
    
        const handleConfirm = () => {
            setTab('')
        }
    
        const renderSplitItem = (key: string) => {
            return (
                <ScrollView className="split-list flex-item" scrollY style={{ height: scrollHeight }}>
                    {
                        condition && condition[key].map((item: any, index: number) => (
                            <View
                                key={index}
                                className={classnames("split-item", selected[key].id === item.id && 'actived')}
                                onClick={() => handleSingleClick(key, item)}
                            >{item.name}
                            </View>
                        ))
                    }
                </ScrollView>
            )
        }
    
        const renderMultiItem = (key: string, title: string = '') => {
            return (
                <View className="search-multi-item">
                    {title && <View className="title">{title}</View>}
                    <View className="options">
                        {
                            condition && condition[key].map((item: any, index: number) => (
                                <View
                                    key={index}
                                    className={classnames("options-item", selected[key].id === item.id && 'actived')}
                                    onClick={() => handleMultiClick(key, item)}
                                >
                                    {item.name}
                                </View>
                            ))
                        }
                    </View>
                </View>
            )
        }
    
        const renderShowName = (item: any) => {
            let showList: string[] = []
            for (const key of item.keys) {
                if (selected[key] instanceof Object) {
                    let showName: string = selected[key].name
                    if (!showName || ['不限', '全部'].includes(showName)) {
                        continue
                    }
                    showList.push(showName)
                }
            }
    
            if (showList.length > 1) {
                showList = ['多选']
            }
    
            return showList.join(',')
        }
        return (
            <View className="newhouse">
                <NavBar title="新房" back={true} />
                <View className="fixed-top" style={{ top: appHeaderHeight }}>
                    <View className="newhouse-header view-content">
                        <View className="newhouse-search">
                            <Text className="iconfont iconsearch"></Text>
                            <Text className="newhouse-search-text placeholder">请输入楼盘名称或地址</Text>
                        </View>
                        <View className="newhouse-nav-right">
                            <Text className="iconfont iconmap"></Text>
                            <Text className="text">地图找房</Text>
                        </View>
                    </View>
                    <View className="search-tab">
                        {
    
                            tabs.map((item: any, index: number) => {
                                let showName = renderShowName(item)
                                return (
                                    <View
                                        key={index}
                                        className={classnames('search-tab-item', showName && 'actived')}
                                        onClick={() => switchCondition(item)}
                                    >
                                        <Text className="text">{showName ? showName : item.name}</Text>
                                        <Text className="iconfont iconarrow-down-bold"></Text>
                                    </View>
                                )
                            })
                        }
                    </View>
                    <View className={classnames('search-container', tab === 'region' && 'actived')}>
                        <View className="search-content">
                            <View className="search-split">
                                <View className="split-type flex-item">
                                    <View className="split-item actived">区域</View>
                                </View>
                                {renderSplitItem('region')}
                            </View>
                        </View>
                    </View>
                    <View className={classnames('search-container', tab === 'price' && 'actived')}>
                        <View className="search-content">
                            <View className="search-split">
                                <View className="split-type flex-item">
                                    {
                                        priceTabs.map((item: any) => (
                                            <View
                                                key={item.id}
                                                className={classnames("split-item", item.value === priceType && 'actived')}
                                                onClick={() => setPriceType(item.value)}>
                                                {item.name}
                                            </View>
                                        ))
                                    }
                                </View>
                                {renderSplitItem(priceType)}
                            </View>
                        </View>
                        {/* <View className="search-footer">
                            <Input className="search-input" placeholder="最低价" />-
                            <Input className="search-input" placeholder="最高价" />
                            <View className="btn confirm-btn single-btn">确定</View>
                        </View> */}
                    </View>
                    <View className={classnames('search-container', tab === 'house_type' && 'actived')}>
                        <View className="search-content">
                            <View className="search-split">
                                {renderSplitItem('house_type')}
                            </View>
                        </View>
                    </View>
                    <View className={classnames('search-container', 'search-multi-container', tab === 'more' && 'actived')}>
                        <ScrollView className="search-content search-content-scroll" scrollY style={{ maxHeight: scrollMoreHeight }}>
                            {renderMultiItem('house_property', '类型')}
                            {renderMultiItem('renovation', '装修')}
                            {renderMultiItem('sale_status', '状态')}
                            {renderMultiItem('feature', '特色')}
                        </ScrollView>
                        <View className="search-footer">
                            <View className="btn reset-btn" onClick={handleReset}>重置</View>
                            <View className="btn confirm-btn" onClick={handleConfirm}>确定</View>
                        </View>
                    </View>
                </View>
                <View className={classnames('mask', tab && 'show')} onClick={() => setTab('')}></View>
    
                <View className="newhouse-content">
                    <ScrollView className="house-list view-content" scrollY style={{ height: contentHeight - 85 }}>
                        <View className="house-list-ul">
                            {
                                houseList.length > 0 && houseList.map((item: any) => (
                                    <View className="house-list-li" key={item.id}>
                                        <View className="li-image">
                                            <Image src={item.image_path}></Image>
                                        </View>
                                        <View className="li-text">
                                            <View className="title mb10">
                                                <Text>{item.house_name}</Text>
                                            </View>
                                            <View className="small-desc mb10">
                                                <Text>{item.area && item.area.name}</Text>
                                                <Text className="line-split"></Text>
                                                <Text>建面{item.building_area}平米</Text>
                                            </View>
                                            <View className="mb10">
                                                <Text className="price">{item.price}</Text>
                                                <Text className="price-unit">{PRICE_TYPE[item.price_type]}</Text>
                                            </View>
                                            <View className="tags">
                                                <Text className={classnames('tags-item', `sale-status-${item.sale_status}`)}>{SALE_STATUS[item.sale_status]}</Text>
                                            </View>
                                        </View>
                                    </View>
                                ))
                            }
                        </View>
                    </ScrollView>
                </View>
            </View>
        )
    }
    export default NewHouse

    图例:

    scss:

    .search-tab {
        display: flex;
        justify-content: center;
        align-items: center;
        height: 80px;
        line-height: 80px;
        font-size: $font-basic;
        border-bottom: $border;
        background-color: $white;
        z-index: 99;
        &-item {
            flex: 1;
            text-align: center;
    
            &.actived {
                color: $primary-color;
    
                .iconfont {
                    color: $primary-color;
                }
            }
    
            .text {
                display: inline-block;
                max-width: 70%;
                white-space: nowrap;
                overflow: hidden;
                text-overflow: ellipsis;
                vertical-align: middle;
            }
    
            .iconfont {
                color: $desc-color;
                margin-left: 10px;
                vertical-align: middle;
            }
        }
    }
    
    .search-container {
        position: absolute;
        width: 100%;
        max-height: 50vh;
        z-index: -10;
        background-color: $white;
        font-size: $font-basic;
        transform: translateY(-100%);
        transition: 0.2s;
        &.actived {
            transform: translateY(0);
        }
        .search-content-scroll {
            margin-bottom: 120px;
        }
        .search-content {
            .search-split {
                display: flex;
    
                .flex-item {
                    flex: 1;
                    border-right: $border;
                }
                .flex-item:last-child {
                    border-right: 0;
                }
                .split-item {
                    height: 80px;
                    line-height: 80px;
                    padding-left: 30px;
                    border-bottom: $border;
                    &.actived {
                        color: $primary-color;
                        background-color: $bg-color;
                    }
                }
            }
    
            .search-multi-item {
                padding: 16px 24px;
                .title {
                    font-size: 30px;
                    color: $title-color;
                    padding: 10px;
                }
    
                .options {
                    display: flex;
                    flex-wrap: wrap;
    
                    &-item {
                        width: 19.5%;
                        margin: 8px;
                        text-align: center;
                        font-size: 24px;
                        padding: 14px 10px;
                        border: 0.5px solid $bg2-color;
                        border-radius: 6px;
                        background-color: $bg2-color;
                        color: $text-color;
    
                        &.actived {
                            color: $primary-color;
                            border-color: $primary-color;
                            background-color: $white;
                        }
                    }
                }
            }
        }
    
        .search-footer {
            position: absolute;
            bottom: 0;
            display: flex;
            width: 100%;
            justify-content: space-around;
            align-items: center;
            padding: 20px 0;
            background-color: #fff;
            .btn {
                width: 40%;
                line-height: 80px;
                text-align: center;
                border-radius: 6px;
    
                &.reset-btn {
                    color: $text-color;
                    background-color: $bg-color;
                }
    
                &.confirm-btn {
                    color: $white;
                    background-color: $primary-color;
                }
    
                &.single-btn {
                    width: 25%;
                }
            }
            .search-input {
                width: 25%;
                height: 80px;
                line-height: 80px;
                text-align: center;
                background-color: $bg-color;
            }
        }
    }
    
    .search-multi-container {
        max-height: 60vh;
    }
  • 相关阅读:
    POJ3094 UVALive3594 HDU2734 ZOJ2812 Quicksum【进制】
    UVALive5583 UVA562 Dividing coins
    POJ1979 HDU1312 Red and Black【DFS】
    POJ1979 HDU1312 Red and Black【DFS】
    POJ2386 Lake Counting【DFS】
    POJ2386 Lake Counting【DFS】
    HDU4394 Digital Square
    HDU4394 Digital Square
    UVA213 UVALive5152 Message Decoding
    UVA213 UVALive5152 Message Decoding
  • 原文地址:https://www.cnblogs.com/Nyan-Workflow-FC/p/13667629.html
Copyright © 2011-2022 走看看