import { BaseEventOrig, InputProps, ScrollView } from '@tarojs/components'; import Taro from '@tarojs/taro'; import { Search } from '@taroify/core'; import { useCallback, useEffect, useState } from 'react'; import { CITY_CODE_TO_NAME_MAP, CITY_INDEXES_LIST, GROUP_CITY_INDEXES_LIST } from '@/constants/city'; import { logWithPrefix } from '@/utils/common'; import './index.less'; interface Item { cityCode: number | string; cityName: string; keyword: string; } const PREFIX = 'search-city'; const HOT_CITY = [ { cityCode: 110100, cityName: '北京' }, { cityCode: 310100, cityName: '上海' }, { cityCode: 440100, cityName: '广州' }, { cityCode: 440300, cityName: '深圳' }, { cityCode: 330100, cityName: '杭州' }, { cityCode: 430100, cityName: '长沙' }, { cityCode: 420100, cityName: '武汉' }, { cityCode: 350200, cityName: '厦门' }, { cityCode: 610100, cityName: '西安' }, { cityCode: 410100, cityName: '郑州' }, { cityCode: 510100, cityName: '成都' }, { cityCode: 340100, cityName: '合肥' }, ]; const OFFSET_INDEX_SIZE = 2; const log = logWithPrefix(PREFIX); const realtimeLogger = Taro.getRealtimeLogManager(); realtimeLogger.tag(PREFIX); const useHeight = () => { const [winHeight, setWinHeight] = useState(0); const [indexItemHeight, setIndexItemHeight] = useState(0); useEffect(() => { const windowInfo = Taro.getWindowInfo(); const windowHeight = windowInfo.windowHeight; setWinHeight(windowHeight); // 上下预留两个选项高度的空白 setIndexItemHeight(Math.floor(windowHeight / (26 + OFFSET_INDEX_SIZE * 2))); }, []); return [winHeight, indexItemHeight]; }; export interface SearchCityProps { onSelectCity: (cityCode: string) => void; currentCity?: string; forGroup?: boolean; banner?: string; offset?: number; } export default function SearchCity({ onSelectCity, currentCity = '', banner = '', forGroup = false, offset = 0, }: SearchCityProps) { const [winHeight, indexItemHeight] = useHeight(); const [touchAnchor, setTouchAnchor] = useState(); const [touchMoving, setTouchMoving] = useState(false); const [searchResult, setSearchResult] = useState([]); const showSearchList = searchResult.length > 0; const CITY_LIST = forGroup ? GROUP_CITY_INDEXES_LIST : CITY_INDEXES_LIST; const handleSearchChange = useCallback((event: BaseEventOrig) => { const value = event.detail.value; log('handleSearchChange', value); if (!value) { setSearchResult([]); return; } const result: Item[] = []; CITY_LIST.forEach(obj => { obj.data.forEach(city => { if (city.keyword.includes(value.toLocaleUpperCase())) { result.push({ ...city }); } }); }); setSearchResult(result); }, []); const handleSelectCity = useCallback( (e: React.MouseEvent) => { const cityCode = e.currentTarget.dataset.code; onSelectCity(String(cityCode)); }, [onSelectCity] ); const handleTouchStart = useCallback( (e: React.TouchEvent) => { const pageY = e.touches[0].pageY; const index = Math.floor(pageY / indexItemHeight) - OFFSET_INDEX_SIZE; if (index < 0 || index >= CITY_LIST.length) { return; } const item = CITY_LIST[index]; if (item) { setTouchMoving(true); setTouchAnchor(item.letter); } }, [indexItemHeight] ); const handleTouchMove = useCallback( (e: React.TouchEvent) => { const pageY = e.touches[0].pageY; const index = Math.floor(pageY / indexItemHeight) - OFFSET_INDEX_SIZE; if (index < 0 || index >= CITY_LIST.length) { return; } const item = CITY_LIST[index]; item && setTouchAnchor(item.letter); }, [indexItemHeight] ); const handleTouchEnd = useCallback((e: React.TouchEvent) => { e.stopPropagation(); setTouchMoving(false); log('touch end'); }, []); const handleClickAnchor = useCallback((anchor: string) => { setTouchAnchor(anchor); log('click anchor', anchor); }, []); return (
{forGroup && banner ? (
{banner}
) : null}
{showSearchList && (
{searchResult.map(city => (
{city.cityName}
))}
)} {!showSearchList && (
当前城市
{CITY_CODE_TO_NAME_MAP.get(currentCity)}
热门城市
{HOT_CITY.map(city => (
{city.cityName}
))}
{CITY_LIST.map(item => { return (
{item.letter}
{item.data.map(city => (
{city.cityName}
))}
); })}
)}
{!showSearchList && (
{CITY_LIST.map(item => { return (
handleClickAnchor(item.letter)} > {item.letter}
); })}
)} {touchAnchor && touchMoving &&
{touchAnchor}
}
); }