react-native开发实例之城市选择组件

城市切换对于地域相关的app使用较多,通常结合定位城市、热门城市、最近选择城市和全部城市列表进行列表展示,另外还提供搜索功能。比较典型的是美团的这个城市选择组件,截图如下。

Paste_Image.png
Paste_Image.png

效果图

1111.gif

使用到的开源项目

几点问题

  • 还没有开发搜索功能,这部分可以本地过滤然后单独的组件展示,也可以远程过滤实时查询
  • 定位、最近访问城市、热门城市没有加入到右边的index条中,这部分比较麻烦,主要是需要对两种不同的数据显示不一样的style,后面考虑继续开发试试
  • 定位功能需要后台支持,这部分目前还不知道怎么做
  • 数据量交大的时候有点卡,可能需要一个loading的界面
  • 我的代码里面出现了3次componentDidMount,分别是读取http接口数据、读取本地json数据和自己mock的几条简单数据,可以分别看看,另外关于ListView控件的row和section如果不清楚可以看看相关文档
  • 页面回退用到的一个this.props.nav是通过外面的Navigator导航组件传递进来的

核心代码如下

Header.js
'use strict';
import React, {Component} from 'react';
import {
    Alert,
    View,
    Text,
    TextInput,
    StyleSheet,
    Platform,
    NavigatorIOS,
    TouchableOpacity,
    StatusBar,
}from 'react-native';
import FontAwesomeIcon from 'react-native-vector-icons/FontAwesome';

export default  class Header extends Component {
    _onBackBtn(e) {
        this.props.nav.pop();
    }
    render() {
        return (
            <View style={styles.container}>
                <StatusBar
                    backgroundColor="#e75404"
                    barStyle="light-content"
                />
                <View style={[styles.cellfixed]}>
                    <TouchableOpacity onPress={e=>this._onBackBtn(e)}>
                        <FontAwesomeIcon name="chevron-left" color="#ffffff" size={20}/>
                    </TouchableOpacity>
                </View>
                <View style={styles.cell}>
                    <Text style={[styles.title]}>{this.props.title}</Text>
                </View>
                <View style={[styles.cellfixed]}>
                </View>
            </View>
        );
    }
}

const styles = StyleSheet.create({
    container: {
        flexDirection: 'row',
        backgroundColor: '#e75404',
        paddingTop: Platform.OS === 'ios' ? 20 : 0,  // 处理iOS状态栏
        height: Platform.OS === 'ios' ? 50 : 35,   // 处理iOS状态栏
        paddingLeft: 5,
        paddingRight: 5,
        paddingBottom: 10,
    },
    cell: {
        flex: 1,
        marginTop: 5,
    },
    title: {
        fontSize: 16,
        textAlign: 'center',
        marginLeft: 5,
        marginRight: 5,
        color: '#ffffff',
    },
    cellfixed: {
        marginTop: 5,
        width: 80,
    },
});
SearchBox.js
'use strict';
import React, {Component}from 'react';
import {
    Alert,
    View,
    Text,
    TextInput,
    StyleSheet,
    Platform,
    NavigatorIOS,
    TouchableOpacity,
    StatusBar,
}from 'react-native';
import FontAwesomeIcon from 'react-native-vector-icons/FontAwesome';

export default class SearchBox extends Component {
    constructor(props) {
        super(props);
    }
    render() {
        return (
            <View style={styles.container}>
                <View style={styles.inputBox}>
                    <View style={styles.inputIcon}>
                        <FontAwesomeIcon name="search" color="#8B8B90" size={20}/>
                    </View>
                    <TextInput style={styles.inputText}
                               underlineColorAndroid="transparent"
                               placeholder={'输入城市名或拼音查询'}>
                    </TextInput>
                </View>
            </View>
        )
    }
}

const styles = StyleSheet.create({
    container: {
        marginTop: 5,
        marginBottom: 5,
        backgroundColor: '#ffffff',
        flexDirection: 'row',
        height: Platform.OS === 'ios' ? 35 : 45,
        borderBottomWidth: StyleSheet.hairlineWidth,
        borderBottomColor: '#cdcdcd',
        paddingBottom:5,
    },
    inputBox: {
        height: Platform.OS === 'ios' ? 30 : 40,
        marginLeft: 5,
        marginRight: 5,
        flex: 1,
        flexDirection: 'row',
        backgroundColor: '#E6E7E8',
    },
    inputIcon: {
        margin: Platform.OS === 'ios' ? 5 : 10,
    },
    inputText: {
        alignSelf: 'flex-end',
        marginTop: Platform.OS === 'ios' ? 0 : 0,
        flex: 1,
        height: Platform.OS === 'ios' ? 30 : 40,
        marginLeft: 2,
        marginRight: 5,
        fontSize: 12,
        lineHeight: 30,
        textAlignVertical: 'bottom',
        textDecorationLine: 'none',
    },

});
index.js
'use strict';
import React, {Component}from 'react';
import {
    Alert,
    View,
    Text,
    TextInput,
    StyleSheet,
    Platform,
    NavigatorIOS,
    TouchableOpacity,
    StatusBar,
    ScrollView,
}from 'react-native';

import Header from '../Header';
import SearchBox from '../SearchBox';
import CityList from './CityIndexListView';


export default class SimpleSelectCity extends Component {
    constructor(props) {
        super(props);
    }
    render() {
        return (
            <View style={styles.container}>
                <Header nav={this.props.nav} title="当前城市:北京" />
                <SearchBox />
                <ScrollView>
                    <CityList nav={this.props.nav}/>
                </ScrollView>
            </View>
        )
    }
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        flexDirection: 'column',
        backgroundColor: '#ffffff',
        // paddingTop: Platform.OS === 'ios' ? 20 : 0,  // 处理iOS状态栏
    },
    currentCity:{
        backgroundColor: '#ffffff',
        height: 20,
        margin:5,
    },
    currentCityText:{
        fontSize:16,
    }
});
CityIndexListView.js
'use strict';
import React, {Component}from 'react';
import  {
    StyleSheet,
    View,
    WebView,
    Text,
    Platform,
    Alert,
    TouchableOpacity,
    ListView,
    Dimensions,
    ScrollView,
} from 'react-native';

import Toast, {DURATION} from 'react-native-easy-toast';


const SECTIONHEIGHT = 30;
const ROWHEIGHT = 40
var totalheight = [];//每个字母对应的城市和字母的总高度


const {width, height} = Dimensions.get('window');
// const URL = 'http://xxxxxxxxx.com/api/city/list';

import DATA_JSON from './city-list.json'


var that;

export default class CityIndexListView extends Component {

    constructor(props) {
        super(props);


        var getSectionData = (dataBlob, sectionID) => {
            return sectionID;
        };
        var getRowData = (dataBlob, sectionID, rowID) => {
            return dataBlob[sectionID][rowID];
        };
        this.state = {
            dataSource: new ListView.DataSource({
                getRowData: getRowData,
                getSectionHeaderData: getSectionData,
                rowHasChanged: (row1, row2) => row1 !== row2,
                sectionHeaderHasChanged: (s1, s2) => s1 !== s2,
            }),
            letters: [],
        };

        that = this;
    }

    _getSortLetters(dataList) {
        let list = [];

        for (let j = 0; j < dataList.length; j++) {
            let sortLetters = dataList[j].sortLetters.toUpperCase();

            let exist = false;
            for (let xx = 0; xx < list.length; xx++) {
                if (list[xx] === sortLetters) {
                    exist = true;
                }
                if (exist) {
                    break;
                }
            }
            if (!exist) {
                list.push(sortLetters);
            }
        }


        return list;
    }

    componentDidMount2() {
        let dataList = {"A": ["阿里", "阿坝"], "B": ["北京", "北方"]};
        let sectionIDs = Object.keys(dataList);
        let rowIDs = sectionIDs.map(sectionID => {
            let thisRow = [];
            let count = dataList[sectionID].length;
            for (let ii = 0; ii < count; ii++) {
                thisRow.push(ii);
            }
            return thisRow;
        });
        this.setState({
            letters: sectionIDs,
            dataSource: this.state.dataSource.cloneWithRowsAndSections(dataList, sectionIDs, rowIDs)
        });


    }
    componentDidMount(){
        let ALL_CITY_LIST = DATA_JSON.allCityList;
        let HOST_CITY_LIST = DATA_JSON.hotCityList;

        let letterList = this._getSortLetters(ALL_CITY_LIST);

        let dataBlob = {};

        ALL_CITY_LIST.map(cityJson=> {
            let key = cityJson.sortLetters.toUpperCase();

            if (dataBlob[key]) {
                let subList = dataBlob[key];
                subList.push(cityJson);
            } else {
                let subList = [];
                subList.push(cityJson);
                dataBlob[key] = subList;
            }
        });


        let sectionIDs = Object.keys(dataBlob);
        let rowIDs = sectionIDs.map(sectionID => {
            let thisRow = [];
            let count = dataBlob[sectionID].length;
            for (let ii = 0; ii < count; ii++) {
                thisRow.push(ii);
            }

            var eachheight = SECTIONHEIGHT + ROWHEIGHT * thisRow.length;
            totalheight.push(eachheight);

            return thisRow;
        });


        this.setState({
            letters: sectionIDs,
            dataSource: this.state.dataSource.cloneWithRowsAndSections(dataBlob, sectionIDs, rowIDs)
        });


        //   Alert.alert('读取list数据', 'sectionIDs.length=>' + sectionIDs.length + ", rowIDs.length=>" + rowIDs.length);

        console.log(sectionIDs);
        console.log(rowIDs);
        console.log(dataBlob);


        this.setState({
            letters: letterList,
            dataSource: this.state.dataSource.cloneWithRowsAndSections(dataBlob, sectionIDs, rowIDs)
        });
    }

    componentDidMount3() {
        fetch(URL, {method: 'GET'}).then((response)=> {
            if (response.ok) {
                return response.json()
            } else {
                Alert.alert('读取list数据', '服务器错误1');
            }
        }).then((json)=> {
            let ALL_CITY_LIST = json.allCityList;
            let HOST_CITY_LIST = json.hotCityList;

            let letterList = this._getSortLetters(ALL_CITY_LIST);

            let dataBlob = {};

            ALL_CITY_LIST.map(cityJson=> {
                let key = cityJson.sortLetters.toUpperCase();

                if (dataBlob[key]) {
                    let subList = dataBlob[key];
                    subList.push(cityJson);
                } else {
                    let subList = [];
                    subList.push(cityJson);
                    dataBlob[key] = subList;
                }
            });

            let sectionIDs = Object.keys(dataBlob);
            let rowIDs = sectionIDs.map(sectionID => {
                let thisRow = [];
                let count = dataBlob[sectionID].length;
                for (let ii = 0; ii < count; ii++) {
                    thisRow.push(ii);
                }
                var eachheight = SECTIONHEIGHT + ROWHEIGHT * thisRow.length;
                totalheight.push(eachheight);

                return thisRow;
            });
            this.setState({
                letters: sectionIDs,
                dataSource: this.state.dataSource.cloneWithRowsAndSections(dataBlob, sectionIDs, rowIDs)
            });

            //   Alert.alert('读取list数据', 'sectionIDs.length=>' + sectionIDs.length + ", rowIDs.length=>" + rowIDs.length);
            console.log(sectionIDs);
            console.log(rowIDs);
            console.log(dataBlob);
            this.setState({
                letters: letterList,
                dataSource: this.state.dataSource.cloneWithRowsAndSections(dataBlob, sectionIDs, rowIDs)
            });
        }).catch((error)=> {
            Alert.alert('读取list数据', '服务器错误2' + error.toString());
        }).done();
    }

    _cityNameClick(cityJson) {
        //this.refs.toast.show(cityJson.name, DURATION.LENGTH_SHORT);
        this.props.nav.pop();
    }
    _scrollTo(index, letter) {
        this.refs.toast.close();
        let position = 0;
        for (let i = 0; i < index; i++) {
            position += totalheight[i]
        }
        this._listView.scrollTo({
            y: position
        });
        this.refs.toast.show(letter, DURATION.LENGTH_SHORT);
    }
    _renderRightLetters(letter, index) {
        return (
            <TouchableOpacity
                key={'letter_idx_' + index}
                activeOpacity={0.6}
                onPress={()=> {
                    this._scrollTo(index, letter)
                }}>
                <View style={styles.letter}>
                    <Text style={styles.letterText}>{letter}</Text>
                </View>
            </TouchableOpacity>
        );
    }
    _renderListRow(cityJson, rowId) {
        return (
            <TouchableOpacity
                key={'list_item_' + cityJson.id}
                style={styles.rowView}
                onPress={()=> {
                    that._cityNameClick(cityJson)
                }}>
                <View style={styles.rowdata}>
                    <Text style={styles.rowdatatext}>{cityJson.name}</Text>
                </View>
            </TouchableOpacity>
        )
    }
    _renderListSectionHeader(sectionData, sectionID) {
        return (
            <View style={  styles.sectionView }>
                <Text style={styles.sectionText}>
                    {sectionData}
                </Text>
            </View>
        );
    }

    render() {
        return (
            <View style={styles.container}>
                <View style={styles.listContainner}>
                    <ListView
                        ref={listView => this._listView = listView}
                        contentContainerStyle={styles.contentContainer}
                        dataSource={this.state.dataSource}
                        renderRow={this._renderListRow}
                        renderSectionHeader={this._renderListSectionHeader}
                        enableEmptySections={true}
                        initialListSize={500}
                    />
                    <View style={styles.letters}>
                        {this.state.letters.map((letter, index) => this._renderRightLetters(letter, index))}
                    </View>
                </View>
                <Toast
                    ref="toast"
                    position='top'
                    positionValue={200}
                    fadeInDuration={750}
                    fadeOutDuration={1000}
                    opacity={0.8}
                />
            </View>
        )
    }
}

const styles = StyleSheet.create({
    container: {
        // paddingTop: 50,
        flex: 1,
        flexDirection: 'column',
        backgroundColor: '#F4F4F4',
        // paddingTop: Platform.OS === 'ios' ? 20 : 0,  // 处理iOS状态栏
    },
    listContainner: {
        height: Dimensions.get('window').height,
        marginBottom: 10
    },
    contentContainer: {
        flexDirection: 'row',
        width: width,
        backgroundColor: 'white',
        justifyContent: 'space-around',
        flexWrap: 'wrap',
    },
    letters: {
        position: 'absolute',
        height: height,
        top: 0,
        bottom: 0,
        right: 10,
        backgroundColor: 'transparent',
        justifyContent: 'flex-start',
        alignItems: 'flex-start',
    },
    letter: {
        height: height * 3.3 / 100,
        width: width * 3 / 50,
        justifyContent: 'center',
        alignItems: 'center',
    },
    letterText: {
        textAlign: 'center',
        fontSize: height * 1.1 / 50,
        color: '#e75404'
    },
    sectionView: {
        paddingTop: 5,
        paddingBottom: 5,
        height: 30,
        paddingLeft: 10,
        width: width,
        backgroundColor: '#F4F4F4',
    },
    sectionText: {
        color: '#e75404',
        fontWeight: 'bold'
    },
    rowView: {
        height: ROWHEIGHT,
        paddingLeft: 10,
        paddingRight: 10,
        borderBottomColor: '#F4F4F4',
        borderBottomWidth: 0.5,
    },
    rowdata: {
        paddingTop: 10,
        paddingBottom: 2,
    },
    rowdatatext: {
        color: 'gray',
        width: width,
    },
});

city-list.json
{
  "allCityList" : [ {
    "name" : "阿坝",
    "spellName" : "aba",
    "id" : 5780,
    "fullname" : "四川/阿坝",
    "sortLetters" : "a"
  }, {
    "name" : "阿克苏",
    "spellName" : "akesudi",
    "id" : 6474,
    "fullname" : "新疆/阿克苏",
    "sortLetters" : "a"
  }, {
    "name" : "阿拉善",
    "spellName" : "alashanmeng",
    "id" : 3862,
    "fullname" : "内蒙古/阿拉善",
    "sortLetters" : "a"
  }, {
    "name" : "阿勒泰",
    "spellName" : "aletaidi",
    "id" : 6542,
    "fullname" : "新疆/阿勒泰",
    "sortLetters" : "a"
  }, {
    "name" : "阿里",
    "spellName" : "alidi",
    "id" : 6134,
    "fullname" : "西藏/阿里",
    "sortLetters" : "a"
  }, {
    "name" : "安康",
    "spellName" : "ankang",
    "id" : 6248,
    "fullname" : "陕西/安康",
    "sortLetters" : "a"
  }, {
    "name" : "安庆",
    "spellName" : "anqing",
    "id" : 4482,
    "fullname" : "安徽/安庆",
    "sortLetters" : "a"
  }, {
    "name" : "鞍山",
    "spellName" : "anshan",
    "id" : 3898,
    "fullname" : "辽宁/鞍山",
    "sortLetters" : "a"
  }, {
    "name" : "安顺",
    "spellName" : "anshun",
    "id" : 5861,
    "fullname" : "贵州/安顺",
    "sortLetters" : "a"
  }, {
    "name" : "安阳",
    "spellName" : "anyang",
    "id" : 4966,
    "fullname" : "河南/安阳",
    "sortLetters" : "a"
  }, {
    "name" : "白城",
    "spellName" : "baicheng",
    "id" : 4041,
    "fullname" : "吉林/白城",
    "sortLetters" : "b"
  }, {
    "name" : "百色",
    "spellName" : "baise",
    "id" : 5527,
    "fullname" : "广西/百色",
    "sortLetters" : "b"
  }, {
    "name" : "白沙",
    "spellName" : "baishalizuz",
    "id" : 5582,
    "fullname" : "海南/白沙",
    "sortLetters" : "b"
  }, {
    "name" : "白山",
    "spellName" : "baishan",
    "id" : 4028,
    "fullname" : "吉林/白山",
    "sortLetters" : "b"
  }, {
    "name" : "白银",
    "spellName" : "baiyin",
    "id" : 6279,
    "fullname" : "甘肃/白银",
    "sortLetters" : "b"
  }, {
    "name" : "蚌埠",
    "spellName" : "bangbu",
    "id" : 4452,
    "fullname" : "安徽/蚌埠",
    "sortLetters" : "b"
  }, {
    "name" : "保定",
    "spellName" : "baoding",
    "id" : 3545,
    "fullname" : "河北/保定",
    "sortLetters" : "b"
  }, {
    "name" : "宝鸡",
    "spellName" : "baoji",
    "id" : 6169,
    "fullname" : "陕西/宝鸡",
    "sortLetters" : "b"
  }, {
    "name" : "保山",
    "spellName" : "baoshan",
    "id" : 5961,
    "fullname" : "云南/保山",
    "sortLetters" : "b"
  }, {
    "name" : "保亭",
    "spellName" : "baotinglizu",
    "id" : 5585,
    "fullname" : "海南/保亭",
    "sortLetters" : "b"
  }, {
    "name" : "包头",
    "spellName" : "baotou",
    "id" : 3770,
    "fullname" : "内蒙古/包头",
    "sortLetters" : "b"
  }, {
    "name" : "巴彦淖尔",
    "spellName" : "bayannaoerm",
    "id" : 3854,
    "fullname" : "内蒙古/巴彦淖尔",
    "sortLetters" : "b"
  }, {
    "name" : "巴音郭楞",
    "spellName" : "bayinguolen",
    "id" : 6501,
    "fullname" : "新疆/巴音郭楞",
    "sortLetters" : "b"
  }, {
    "name" : "巴中",
    "spellName" : "bazhong",
    "id" : 5770,
    "fullname" : "四川/巴中",
    "sortLetters" : "b"
  }, {
    "name" : "北海",
    "spellName" : "beihai",
    "id" : 5501,
    "fullname" : "广西/北海",
    "sortLetters" : "b"
  }, {
    "name" : "北京",
    "spellName" : "beijing",
    "id" : 6550,
    "fullname" : "北京/北京",
    "sortLetters" : "b"
  }, {
    "name" : "本溪",
    "spellName" : "benxi",
    "id" : 3914,
    "fullname" : "辽宁/本溪",
    "sortLetters" : "b"
  }, {
    "name" : "毕节地",
    "spellName" : "bijiedi",
    "id" : 5879,
    "fullname" : "贵州/毕节地",
    "sortLetters" : "b"
  }, {
    "name" : "滨州",
    "spellName" : "binzhou",
    "id" : 4867,
    "fullname" : "山东/滨州",
    "sortLetters" : "b"
  }, {
    "name" : "博尔塔拉",
    "spellName" : "boertala",
    "id" : 6520,
    "fullname" : "新疆/博尔塔拉",
    "sortLetters" : "b"
  }, {
    "name" : "沧州",
    "spellName" : "cangzhou",
    "id" : 3601,
    "fullname" : "河北/沧州",
    "sortLetters" : "c"
  }, {
    "name" : "长春",
    "spellName" : "changchun",
    "id" : 3987,
    "fullname" : "吉林/长春",
    "sortLetters" : "c"
  }, {
    "name" : "常德",
    "spellName" : "changde",
    "id" : 5235,
    "fullname" : "湖南/常德",
    "sortLetters" : "c"
  }, {
    "name" : "昌都",
    "spellName" : "changdudi",
    "id" : 6090,
    "fullname" : "西藏/昌都",
    "sortLetters" : "c"
  }, {
    "name" : "昌吉",
    "spellName" : "changji",
    "id" : 6511,
    "fullname" : "新疆/昌吉",
    "sortLetters" : "c"
  }, {
    "name" : "昌江",
    "spellName" : "changjiangl",
    "id" : 5581,
    "fullname" : "海南/昌江",
    "sortLetters" : "c"
  }, {
    "name" : "长沙",
    "spellName" : "changsha",
    "id" : 5174,
    "fullname" : "湖南/长沙",
    "sortLetters" : "c"
  }, {
    "name" : "长治",
    "spellName" : "changzhi",
    "id" : 3667,
    "fullname" : "山西/长治",
    "sortLetters" : "c"
  }, {
    "name" : "常州",
    "spellName" : "changzhou",
    "id" : 4309,
    "fullname" : "江苏/常州",
    "sortLetters" : "c"
  }, {
    "name" : "巢湖",
    "spellName" : "chaohu",
    "id" : 4526,
    "fullname" : "安徽/巢湖",
    "sortLetters" : "c"
  }, {
    "name" : "朝阳",
    "spellName" : "chaoyang",
    "id" : 3979,
    "fullname" : "辽宁/朝阳",
    "sortLetters" : "c"
  }, {
    "name" : "潮州",
    "spellName" : "chaozhou",
    "id" : 5436,
    "fullname" : "广东/潮州",
    "sortLetters" : "c"
  }, {
    "name" : "承德",
    "spellName" : "chengde",
    "id" : 3589,
    "fullname" : "河北/承德",
    "sortLetters" : "c"
  }, {
    "name" : "成都",
    "spellName" : "chengdu",
    "id" : 5630,
    "fullname" : "四川/成都",
    "sortLetters" : "c"
  }, {
    "name" : "澄迈",
    "spellName" : "chengmai",
    "id" : 5578,
    "fullname" : "海南/澄迈",
    "sortLetters" : "c"
  }, {
    "name" : "郴州",
    "spellName" : "chenzhou",
    "id" : 5257,
    "fullname" : "湖南/郴州",
    "sortLetters" : "c"
  }, {
    "name" : "赤峰",
    "spellName" : "chifeng",
    "id" : 3784,
    "fullname" : "内蒙古/赤峰",
    "sortLetters" : "c"
  }, {
    "name" : "池州",
    "spellName" : "chizhou",
    "id" : 4545,
    "fullname" : "安徽/池州",
    "sortLetters" : "c"
  }, {
    "name" : "重庆",
    "spellName" : "chongqing",
    "id" : 5587,
    "fullname" : "重庆/重庆",
    "sortLetters" : "c"
  }, {
    "name" : "崇左",
    "spellName" : "chongzuo",
    "id" : 5563,
    "fullname" : "广西/崇左",
    "sortLetters" : "c"
  }, {
    "name" : "楚雄",
    "spellName" : "chuxiong",
    "id" : 6031,
    "fullname" : "云南/楚雄",
    "sortLetters" : "c"
  }, {
    "name" : "滁州",
    "spellName" : "chuzhou",
    "id" : 4502,
    "fullname" : "安徽/滁州",
    "sortLetters" : "c"
  }, {
    "name" : "大理",
    "spellName" : "dali",
    "id" : 6042,
    "fullname" : "云南/大理",
    "sortLetters" : "d"
  }, {
    "name" : "大连",
    "spellName" : "dalian",
    "id" : 3887,
    "fullname" : "辽宁/大连",
    "sortLetters" : "d"
  }, {
    "name" : "丹东",
    "spellName" : "dandong",
    "id" : 3921,
    "fullname" : "辽宁/丹东",
    "sortLetters" : "d"
  }, {
    "name" : "大庆",
    "spellName" : "daqing",
    "id" : 4120,
    "fullname" : "黑龙江/大庆",
    "sortLetters" : "d"
  }, {
    "name" : "大同",
    "spellName" : "datong",
    "id" : 3651,
    "fullname" : "山西/大同",
    "sortLetters" : "d"
  }, {
    "name" : "大兴安岭",
    "spellName" : "daxinganlin",
    "id" : 4194,
    "fullname" : "黑龙江/大兴安岭",
    "sortLetters" : "d"
  }, {
    "name" : "达州",
    "spellName" : "dazhou",
    "id" : 5746,
    "fullname" : "四川/达州",
    "sortLetters" : "d"
  }, {
    "name" : "德宏",
    "spellName" : "dehong",
    "id" : 6055,
    "fullname" : "云南/德宏",
    "sortLetters" : "d"
  }, {
    "name" : "德阳",
    "spellName" : "deyang",
    "id" : 5671,
    "fullname" : "四川/德阳",
    "sortLetters" : "d"
  }, {
    "name" : "德州",
    "spellName" : "dezhou",
    "id" : 4846,
    "fullname" : "山东/德州",
    "sortLetters" : "d"
  }, {
    "name" : "定安",
    "spellName" : "dingan",
    "id" : 5579,
    "fullname" : "海南/定安",
    "sortLetters" : "d"
  }, {
    "name" : "定西",
    "spellName" : "dingxidi",
    "id" : 6331,
    "fullname" : "甘肃/定西",
    "sortLetters" : "d"
  }, {
    "name" : "迪庆",
    "spellName" : "diqing",
    "id" : 6066,
    "fullname" : "云南/迪庆",
    "sortLetters" : "d"
  }, {
    "name" : "东莞",
    "spellName" : "dongwan",
    "id" : 5380,
    "fullname" : "广东/东莞",
    "sortLetters" : "d"
  }, {
    "name" : "东营",
    "spellName" : "dongying",
    "id" : 4781,
    "fullname" : "山东/东营",
    "sortLetters" : "d"
  }, {
    "name" : "鄂尔多斯",
    "spellName" : "eerduosi",
    "id" : 3806,
    "fullname" : "内蒙古/鄂尔多斯",
    "sortLetters" : "e"
  }, {
    "name" : "恩施",
    "spellName" : "enshi",
    "id" : 5162,
    "fullname" : "湖北/恩施",
    "sortLetters" : "e"
  }, {
    "name" : "鄂州",
    "spellName" : "ezhou",
    "id" : 5129,
    "fullname" : "湖北/鄂州",
    "sortLetters" : "e"
  }, {
    "name" : "防城港",
    "spellName" : "fangchengga",
    "id" : 5506,
    "fullname" : "广西/防城港",
    "sortLetters" : "f"
  }, {
    "name" : "佛山",
    "spellName" : "foshan",
    "id" : 5390,
    "fullname" : "广东/佛山",
    "sortLetters" : "f"
  }, {
    "name" : "抚顺",
    "spellName" : "fushun",
    "id" : 3906,
    "fullname" : "辽宁/抚顺",
    "sortLetters" : "f"
  }, {
    "name" : "阜新",
    "spellName" : "fuxin",
    "id" : 3955,
    "fullname" : "辽宁/阜新",
    "sortLetters" : "f"
  }, {
    "name" : "阜阳",
    "spellName" : "fuyang",
    "id" : 4511,
    "fullname" : "安徽/阜阳",
    "sortLetters" : "f"
  }, {
    "name" : "抚州",
    "spellName" : "fuzhou",
    "id" : 4718,
    "fullname" : "江西/抚州",
    "sortLetters" : "f"
  }, {
    "name" : "福州",
    "spellName" : "fuzhou",
    "id" : 4558,
    "fullname" : "福建/福州",
    "sortLetters" : "f"
  }, {
    "name" : "甘南",
    "spellName" : "gannan",
    "id" : 6349,
    "fullname" : "甘肃/甘南",
    "sortLetters" : "g"
  }, {
    "name" : "赣州",
    "spellName" : "ganzhou",
    "id" : 4677,
    "fullname" : "江西/赣州",
    "sortLetters" : "g"
  }, {
    "name" : "甘孜",
    "spellName" : "ganzi",
    "id" : 5794,
    "fullname" : "四川/甘孜",
    "sortLetters" : "g"
  }, {
    "name" : "广安",
    "spellName" : "guangan",
    "id" : 5740,
    "fullname" : "四川/广安",
    "sortLetters" : "g"
  }, {
    "name" : "广元",
    "spellName" : "guangyuan",
    "id" : 5688,
    "fullname" : "四川/广元",
    "sortLetters" : "g"
  }, {
    "name" : "广州",
    "spellName" : "guangzhou",
    "id" : 5308,
    "fullname" : "广东/广州",
    "sortLetters" : "g"
  }, {
    "name" : "贵港",
    "spellName" : "guigang",
    "id" : 5516,
    "fullname" : "广西/贵港",
    "sortLetters" : "g"
  }, {
    "name" : "桂林",
    "spellName" : "guilin",
    "id" : 5475,
    "fullname" : "广西/桂林",
    "sortLetters" : "g"
  }, {
    "name" : "贵阳",
    "spellName" : "guiyang",
    "id" : 5831,
    "fullname" : "贵州/贵阳",
    "sortLetters" : "g"
  }, {
    "name" : "果洛",
    "spellName" : "guoluo",
    "id" : 6398,
    "fullname" : "青海/果洛",
    "sortLetters" : "g"
  }, {
    "name" : "固原",
    "spellName" : "guyuan",
    "id" : 6436,
    "fullname" : "宁夏/固原",
    "sortLetters" : "g"
  }, {
    "name" : "哈尔滨",
    "spellName" : "haerbin",
    "id" : 4056,
    "fullname" : "黑龙江/哈尔滨",
    "sortLetters" : "h"
  }, {
    "name" : "海北",
    "spellName" : "haibei",
    "id" : 6382,
    "fullname" : "青海/海北",
    "sortLetters" : "h"
  }, {
    "name" : "海东",
    "spellName" : "haidongdi",
    "id" : 6375,
    "fullname" : "青海/海东",
    "sortLetters" : "h"
  }, {
    "name" : "海口",
    "spellName" : "haikou",
    "id" : 5570,
    "fullname" : "海南/海口",
    "sortLetters" : "h"
  }, {
    "name" : "海南",
    "spellName" : "hainan",
    "id" : 6392,
    "fullname" : "青海/海南",
    "sortLetters" : "h"
  }, {
    "name" : "海西",
    "spellName" : "haixi",
    "id" : 6412,
    "fullname" : "青海/海西",
    "sortLetters" : "h"
  }, {
    "name" : "哈密",
    "spellName" : "hamidi",
    "id" : 6461,
    "fullname" : "新疆/哈密",
    "sortLetters" : "h"
  }, {
    "name" : "邯郸",
    "spellName" : "handan",
    "id" : 3505,
    "fullname" : "河北/邯郸",
    "sortLetters" : "h"
  }, {
    "name" : "杭州",
    "spellName" : "hangzhou",
    "id" : 4337,
    "fullname" : "浙江/杭州",
    "sortLetters" : "h"
  }, {
    "name" : "汉中",
    "spellName" : "hanzhong",
    "id" : 6223,
    "fullname" : "陕西/汉中",
    "sortLetters" : "h"
  }, {
    "name" : "亳州",
    "spellName" : "haozhou",
    "id" : 4540,
    "fullname" : "安徽/亳州",
    "sortLetters" : "h"
  }, {
    "name" : "漯河",
    "spellName" : "he",
    "id" : 4990,
    "fullname" : "河南/漯河",
    "sortLetters" : "h"
  }, {
    "name" : "鹤壁",
    "spellName" : "hebi",
    "id" : 4947,
    "fullname" : "河南/鹤壁",
    "sortLetters" : "h"
  }, {
    "name" : "河池",
    "spellName" : "hechi",
    "id" : 5544,
    "fullname" : "广西/河池",
    "sortLetters" : "h"
  }, {
    "name" : "合肥",
    "spellName" : "hefei",
    "id" : 4436,
    "fullname" : "安徽/合肥",
    "sortLetters" : "h"
  }, {
    "name" : "鹤岗",
    "spellName" : "hegang",
    "id" : 4092,
    "fullname" : "黑龙江/鹤岗",
    "sortLetters" : "h"
  }, {
    "name" : "黑河",
    "spellName" : "heihe",
    "id" : 4176,
    "fullname" : "黑龙江/黑河",
    "sortLetters" : "h"
  }, {
    "name" : "衡水",
    "spellName" : "hengshui",
    "id" : 3629,
    "fullname" : "河北/衡水",
    "sortLetters" : "h"
  }, {
    "name" : "衡阳",
    "spellName" : "hengyang",
    "id" : 5200,
    "fullname" : "湖南/衡阳",
    "sortLetters" : "h"
  }, {
    "name" : "和田",
    "spellName" : "hetiandi",
    "id" : 6465,
    "fullname" : "新疆/和田",
    "sortLetters" : "h"
  }, {
    "name" : "河源",
    "spellName" : "heyuan",
    "id" : 5353,
    "fullname" : "广东/河源",
    "sortLetters" : "h"
  }, {
    "name" : "菏泽",
    "spellName" : "heze",
    "id" : 4875,
    "fullname" : "山东/菏泽",
    "sortLetters" : "h"
  }, {
    "name" : "贺州",
    "spellName" : "hezhou",
    "id" : 5539,
    "fullname" : "广西/贺州",
    "sortLetters" : "h"
  }, {
    "name" : "红河",
    "spellName" : "honghe",
    "id" : 6013,
    "fullname" : "云南/红河",
    "sortLetters" : "h"
  }, {
    "name" : "淮安",
    "spellName" : "huaian",
    "id" : 4253,
    "fullname" : "江苏/淮安",
    "sortLetters" : "h"
  }, {
    "name" : "淮北",
    "spellName" : "huaibei",
    "id" : 4472,
    "fullname" : "安徽/淮北",
    "sortLetters" : "h"
  }, {
    "name" : "怀化",
    "spellName" : "huaihua",
    "id" : 5281,
    "fullname" : "湖南/怀化",
    "sortLetters" : "h"
  }, {
    "name" : "淮南",
    "spellName" : "huainan",
    "id" : 4460,
    "fullname" : "安徽/淮南",
    "sortLetters" : "h"
  }, {
    "name" : "黄冈",
    "spellName" : "huanggang",
    "id" : 5141,
    "fullname" : "湖北/黄冈",
    "sortLetters" : "h"
  }, {
    "name" : "黄南",
    "spellName" : "huangnan",
    "id" : 6387,
    "fullname" : "青海/黄南",
    "sortLetters" : "h"
  }, {
    "name" : "黄山",
    "spellName" : "huangshan",
    "id" : 4494,
    "fullname" : "安徽/黄山",
    "sortLetters" : "h"
  }, {
    "name" : "黄石",
    "spellName" : "huangshi",
    "id" : 5074,
    "fullname" : "湖北/黄石",
    "sortLetters" : "h"
  }, {
    "name" : "呼和浩特",
    "spellName" : "huhehaote",
    "id" : 3760,
    "fullname" : "内蒙古/呼和浩特",
    "sortLetters" : "h"
  }, {
    "name" : "惠州",
    "spellName" : "huizhou",
    "id" : 5369,
    "fullname" : "广东/惠州",
    "sortLetters" : "h"
  }, {
    "name" : "葫芦岛",
    "spellName" : "huludao",
    "id" : 3936,
    "fullname" : "辽宁/葫芦岛",
    "sortLetters" : "h"
  }, {
    "name" : "呼伦贝尔",
    "spellName" : "hulunbeier",
    "id" : 3815,
    "fullname" : "内蒙古/呼伦贝尔",
    "sortLetters" : "h"
  }, {
    "name" : "湖州",
    "spellName" : "huzhou",
    "id" : 4383,
    "fullname" : "浙江/湖州",
    "sortLetters" : "h"
  }, {
    "name" : "佳木斯",
    "spellName" : "jiamusi",
    "id" : 4159,
    "fullname" : "黑龙江/佳木斯",
    "sortLetters" : "j"
  }, {
    "name" : "吉安",
    "spellName" : "jian",
    "id" : 4695,
    "fullname" : "江西/吉安",
    "sortLetters" : "j"
  }, {
    "name" : "江门",
    "spellName" : "jiangmen",
    "id" : 5382,
    "fullname" : "广东/江门",
    "sortLetters" : "j"
  }, {
    "name" : "焦作",
    "spellName" : "jiaozuo",
    "id" : 4936,
    "fullname" : "河南/焦作",
    "sortLetters" : "j"
  }, {
    "name" : "嘉兴",
    "spellName" : "jiaxing",
    "id" : 4375,
    "fullname" : "浙江/嘉兴",
    "sortLetters" : "j"
  }, {
    "name" : "嘉峪关",
    "spellName" : "jiayuguan",
    "id" : 6293,
    "fullname" : "甘肃/嘉峪关",
    "sortLetters" : "j"
  }, {
    "name" : "嘉峪关",
    "spellName" : "Jiayuguan",
    "id" : 6556,
    "fullname" : "甘肃/嘉峪关/嘉峪关",
    "sortLetters" : "J"
  }, {
    "name" : "揭阳",
    "spellName" : "jieyang",
    "id" : 5440,
    "fullname" : "广东/揭阳",
    "sortLetters" : "j"
  }, {
    "name" : "吉林",
    "spellName" : "jilin",
    "id" : 3998,
    "fullname" : "吉林/吉林",
    "sortLetters" : "j"
  }, {
    "name" : "济南",
    "spellName" : "jinan",
    "id" : 4741,
    "fullname" : "山东/济南",
    "sortLetters" : "j"
  }, {
    "name" : "金昌",
    "spellName" : "jinchang",
    "id" : 6276,
    "fullname" : "甘肃/金昌",
    "sortLetters" : "j"
  }, {
    "name" : "晋城",
    "spellName" : "jincheng",
    "id" : 3680,
    "fullname" : "山西/晋城",
    "sortLetters" : "j"
  }, {
    "name" : "景德镇",
    "spellName" : "jingdezhen",
    "id" : 4651,
    "fullname" : "江西/景德镇",
    "sortLetters" : "j"
  }, {
    "name" : "荆门",
    "spellName" : "jingmen",
    "id" : 5123,
    "fullname" : "湖北/荆门",
    "sortLetters" : "j"
  }, {
    "name" : "荆州",
    "spellName" : "jingzhou",
    "id" : 5100,
    "fullname" : "湖北/荆州",
    "sortLetters" : "j"
  }, {
    "name" : "金华",
    "spellName" : "jinhua",
    "id" : 4394,
    "fullname" : "浙江/金华",
    "sortLetters" : "j"
  }, {
    "name" : "济宁",
    "spellName" : "jining",
    "id" : 4818,
    "fullname" : "山东/济宁",
    "sortLetters" : "j"
  }, {
    "name" : "晋中",
    "spellName" : "jinzhong",
    "id" : 3692,
    "fullname" : "山西/晋中",
    "sortLetters" : "j"
  }, {
    "name" : "锦州",
    "spellName" : "jinzhou",
    "id" : 3928,
    "fullname" : "辽宁/锦州",
    "sortLetters" : "j"
  }, {
    "name" : "九江",
    "spellName" : "jiujiang",
    "id" : 4660,
    "fullname" : "江西/九江",
    "sortLetters" : "j"
  }, {
    "name" : "酒泉",
    "spellName" : "jiuquan",
    "id" : 6314,
    "fullname" : "甘肃/酒泉",
    "sortLetters" : "j"
  }, {
    "name" : "鸡西",
    "spellName" : "jixi",
    "id" : 4110,
    "fullname" : "黑龙江/鸡西",
    "sortLetters" : "j"
  }, {
    "name" : "开封",
    "spellName" : "kaifeng",
    "id" : 4898,
    "fullname" : "河南/开封",
    "sortLetters" : "k"
  }, {
    "name" : "喀什",
    "spellName" : "kashidi",
    "id" : 6484,
    "fullname" : "新疆/喀什",
    "sortLetters" : "k"
  }, {
    "name" : "克拉玛依",
    "spellName" : "kelamayi",
    "id" : 6451,
    "fullname" : "新疆/克拉玛依",
    "sortLetters" : "k"
  }, {
    "name" : "克孜勒苏",
    "spellName" : "kezilesu",
    "id" : 6497,
    "fullname" : "新疆/克孜勒苏",
    "sortLetters" : "k"
  }, {
    "name" : "昆明",
    "spellName" : "kunming",
    "id" : 5927,
    "fullname" : "云南/昆明",
    "sortLetters" : "k"
  }, {
    "name" : "来宾",
    "spellName" : "laibin",
    "id" : 5556,
    "fullname" : "广西/来宾",
    "sortLetters" : "l"
  }, {
    "name" : "莱芜",
    "spellName" : "laiwu",
    "id" : 4830,
    "fullname" : "山东/莱芜",
    "sortLetters" : "l"
  }, {
    "name" : "廊坊",
    "spellName" : "langfang",
    "id" : 3618,
    "fullname" : "河北/廊坊",
    "sortLetters" : "l"
  }, {
    "name" : "兰州",
    "spellName" : "lanzhou",
    "id" : 6267,
    "fullname" : "甘肃/兰州",
    "sortLetters" : "l"
  }, {
    "name" : "拉萨",
    "spellName" : "lasa",
    "id" : 6070,
    "fullname" : "西藏/拉萨",
    "sortLetters" : "l"
  }, {
    "name" : "乐东",
    "spellName" : "ledonglizuz",
    "id" : 5586,
    "fullname" : "海南/乐东",
    "sortLetters" : "l"
  }, {
    "name" : "乐山",
    "spellName" : "leshan",
    "id" : 5707,
    "fullname" : "四川/乐山",
    "sortLetters" : "l"
  }, {
    "name" : "凉山",
    "spellName" : "liangshan",
    "id" : 5813,
    "fullname" : "四川/凉山",
    "sortLetters" : "l"
  }, {
    "name" : "连云港",
    "spellName" : "lianyungang",
    "id" : 4245,
    "fullname" : "江苏/连云港",
    "sortLetters" : "l"
  }, {
    "name" : "聊城",
    "spellName" : "liaocheng",
    "id" : 4858,
    "fullname" : "山东/聊城",
    "sortLetters" : "l"
  }, {
    "name" : "辽阳",
    "spellName" : "liaoyang",
    "id" : 3963,
    "fullname" : "辽宁/辽阳",
    "sortLetters" : "l"
  }, {
    "name" : "辽源",
    "spellName" : "liaoyuan",
    "id" : 4015,
    "fullname" : "吉林/辽源",
    "sortLetters" : "l"
  }, {
    "name" : "丽江",
    "spellName" : "lijiang",
    "id" : 5999,
    "fullname" : "云南/丽江",
    "sortLetters" : "l"
  }, {
    "name" : "临沧",
    "spellName" : "lincangdi",
    "id" : 5990,
    "fullname" : "云南/临沧",
    "sortLetters" : "l"
  }, {
    "name" : "临汾",
    "spellName" : "linfen",
    "id" : 3730,
    "fullname" : "山西/临汾",
    "sortLetters" : "l"
  }, {
    "name" : "陵水",
    "spellName" : "lingshuiliz",
    "id" : 5584,
    "fullname" : "海南/陵水",
    "sortLetters" : "l"
  }, {
    "name" : "临夏",
    "spellName" : "linxia",
    "id" : 6358,
    "fullname" : "甘肃/临夏",
    "sortLetters" : "l"
  }, {
    "name" : "临沂",
    "spellName" : "linyi",
    "id" : 4833,
    "fullname" : "山东/临沂",
    "sortLetters" : "l"
  }, {
    "name" : "林芝",
    "spellName" : "linzhidi",
    "id" : 6142,
    "fullname" : "西藏/林芝",
    "sortLetters" : "l"
  }, {
    "name" : "丽水",
    "spellName" : "lishui",
    "id" : 4426,
    "fullname" : "浙江/丽水",
    "sortLetters" : "l"
  }, {
    "name" : "六安",
    "spellName" : "liuan",
    "id" : 4532,
    "fullname" : "安徽/六安",
    "sortLetters" : "l"
  }, {
    "name" : "六盘水",
    "spellName" : "liupanshui",
    "id" : 5842,
    "fullname" : "贵州/六盘水",
    "sortLetters" : "l"
  }, {
    "name" : "柳州",
    "spellName" : "liuzhou",
    "id" : 5464,
    "fullname" : "广西/柳州",
    "sortLetters" : "l"
  } ],
  "bcode" : 0
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,029评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,395评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,570评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,535评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,650评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,850评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,006评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,747评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,207评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,536评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,683评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,342评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,964评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,772评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,004评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,401评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,566评论 2 349

推荐阅读更多精彩内容