123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204 |
- import React, { Component } from 'react';
- import { NavBar, SearchBar, WhiteSpace, List, Toast, Icon } from 'antd-mobile';
- import { SearchMask, IndexNav, Indicator, PositionCity, SearchArea } from '../../components';
- import { getLocalCity } from '../../services/locationServices';
- import {
- LASTEST_CITY,
- getAllCities,
- saveLocalStorageCity,
- getLocalStorageCity,
- searchCityByName,
- transformCityMenuData
- } from '../../services/cityServices';
- import { throttle } from '../../utils';
- import './city.css';
- const Item = List.Item;
- const searchCity = throttle(searchCityByName);
- class City extends Component {
- constructor(props) {
- super(props);
- this.state = {
- localCity: '北京',
- hotCity: [],
- latestCity: [],
- city: {},
- labels: [],
- searchCities: [],
- moving: false,
- indicator: '',
- loading: false,
- searchArea: false
- };
- }
- componentDidMount = () => {
- this.setState(() => {
- Toast.loading('Loading...');
- return { loading: true };
- });
- Promise.all([getLocalCity(), getAllCities(), getLocalStorageCity(LASTEST_CITY)]).then(result => {
- const localCity = result[0] && result[0].replace(/市/, '');
- const city = result[1].afterFilterAllCity.allCity;
- const labels = result[1].afterFilterAllCity.validateLetters;
- const hotCity = result[1].hotCity;
- const latestCity = result[2];
- this.setState(() => {
- Toast.hide();
- return {
- localCity,
- city,
- hotCity,
- labels,
- latestCity,
- loading: false
- };
- });
- });
- }
- onSearchInput = async value => {
- if (!value) {
- this.hideMenuDialog();
- return;
- }
- const { labels, city } = this.state;
- const cities = await searchCity(value, labels, city);
- this.setState({
- searchArea: true,
- searchCities: transformCityMenuData(cities)
- });
- }
- hideMenuDialog = () => {
- this.setState({
- searchArea: false,
- searchCities: []
- });
- }
- renderLocalCity = () => {
- const { localCity, latestCity } = this.state;
- return <PositionCity
- title={ '定位/最近访问' }
- position
- positionCity={ localCity }
- city={ latestCity }
- onSelectCity={ this.onSelectCity } />
- }
- renderHotCity = () => {
- const { hotCity } = this.state;
- return <PositionCity
- title={ '热门城市' }
- position={ false }
- city={ hotCity }
- onSelectCity={ this.onSelectCity } />
- }
- renderCities = () => {
- const { city } = this.state;
- return Object.keys(city).map(letter => {
- const cList = city[letter];
- return (
- <div key={ letter } ref={ element => this[`section${letter}`] = element }>
- <List renderHeader={ () => letter } className="select-city-list">
- {
- cList.length > 0 && cList.map(c => {
- return <Item key={ c.id } onClick={ () => this.onSelectCity(c) }>{ c.city }</Item>
- })
- }
- </List>
- </div>
- );
- });
- }
- renderSearchCity = () => {
- const { searchCities } = this.state;
- return <SearchArea city={ searchCities } onChange={ this.onChangeMenu } />
- }
- onChangeMenu = value => {
- this.hideMenuDialog();
- this.onSelectCity(value[0]);
- }
- onSelectCity = (city) => {
- if (this.state.moving) {
- return;
- }
- const { history, location } = this.props;
- const { cityCode, ...rest } = location.state;
- const backCity = typeof city === 'string' ? city : city.city;
- rest[`city${cityCode}`] = backCity;
- saveLocalStorageCity(LASTEST_CITY, backCity);
- history.push({
- pathname: '/',
- state: { ...rest }
- });
- }
- onNavChange = (nav) => {
- this.setState(() => {
- const label = nav.label ? nav.label : this.state.label;
- const moving = nav.moving ? nav.moving : this.state.moving;
- this[`section${label}`] && this[`section${label}`].scrollIntoView();
- return {
- moving,
- indicator: label
- }
- });
- }
- render() {
- const { labels, indicator, moving, loading, searchArea } = this.state;
- if (loading) {
- return null;
- }
- return (
- <div className="city">
- <div className="city-top">
- <NavBar
- className="navbar"
- mode="dark"
- icon={ <Icon type="left" /> }
- leftContent="返回"
- onLeftClick={ () => this.props.history.goBack() }
- >选择城市</NavBar>
- <SearchBar
- placeholder="请输入你要选择的城市"
- maxLength={ 8 }
- onChange={ this.onSearchInput } />
- </div>
- <div className="city-list">
- <div className="city-search-area">
- { searchArea && this.renderSearchCity() }
- </div>
- <SearchMask show={ searchArea } city={ this.state.searchCities } />
- <div className="city-list-content">
- { this.renderLocalCity() }
- <WhiteSpace size="md" />
- { this.renderHotCity() }
- { this.renderCities() }
- <Indicator indicator={ indicator } />
- </div>
- <div className="city-label">
- <IndexNav labels={ labels } moving={ moving } onNavChange={ this.onNavChange } />
- </div>
- </div>
- </div>
-
- );
- }
- }
- export default City;
|