nodeJS开发一套完整的项目(6、省市县模块)

本章节我们谈谈省市县模块的编写,我们先把城市的基础数据展示出来,然后我们看看如何在后面如何调用。

城市基础数据

我们在initData文件夹里创建cities.js文件,里面是城市数据。由于数据量比较大,在这里无法贴出,后面我会把下载地址放出来。

创建城市model

在web->models->v1文件夹下创建city.js文件,具体代码如下:

/**
 * Created by admin on 2017/9/28 0020.
 */
'use strict';
import mongoose from 'mongoose';
import cityData from '../../../initData/cities';

const citySchema = new mongoose.Schema({
    data:{}
});

//添加 mongoose 静态方法,静态方法在Model层就能使用,statics是静态方法。methods是实例方法
citySchema.statics.cityGuess = function(name) {
   /* promise是一个异步编程的抽象,它是一个返回值或抛出exception的代理对象,
    一般promise对象都有一个then方法,这个then方法是我们如何获得返回值(成功实现承诺的结果值,称为fulfillment)
    或抛出exception(拒绝承诺的理由,称为rejection),then是用两个可选的回调作为参数
    Async/await的主要益处是可以避免回调地狱(callback hell)问题。
    async 表示这是一个async函数,await只能用在这个函数里面。async 对象也是一个 promise 对象。
    await 表示在这里等待promise返回结果了,再继续执行。
    await 后面跟着的应该是一个promise对象(当然,其他返回值也没关系,不过那样就没有意义了…)
    */
    return new Promise(async (resolve, reject) => {
        const firstWord = name.substr(0,1).toUpperCase();
        try{
            const city = await this.findOne();
            //Object.entries返回的是二维数组
            Object.entries(city.data).forEach(item => {
                if(item[0] == firstWord) {
                    item[1].forEach(cityItem => {
                        if(cityItem.pinyin == name) {
                            resolve(cityItem);
                        }
                    })
                }
            });
        } catch(err) {
            reject({
                name: 'ERROR_DATA',
                message: '查找数据失败'
            });
            console.error(err);
        }
    });
};

//热门城市
citySchema.statics.cityHot = function() {
    return new Promise(async (resolve,reject) => {
        try{
            const city = await this.findOne();
            resolve(city.data.hotCities);
        } catch(err) {
            reject({
                name: 'ERROR_DATA',
                message: '查找数据失败'
            });
            console.error(err);
        }
    });
};

//获取所有城市
citySchema.statics.cityGroup = function() {
    return new Promist(async (resolve,reject) => {
        try{
            const city = await this.findOne();
            const cityObj = city.data;
            delete(cityObj._id);
            delete(cityObj.hotCities);
            resolve(cityObj);
        } catch(err) {
            reject({
                name: 'ERROR_DATA',
                message: '查找数据失败'
            });
            console.error(err);
        }
    });
};

//根据城市ID获取城市信息
citySchema.statics.getCityById = function(id) {
    return new Promise(async (resolve,reject) => {
        try{
            const city = await this.findOne();
            Object.entries(city.data).forEach(item => {
                if(item[0] !== '_id'  && item[0] !== 'hotCities') {
                    item[1].forEach(cityItem => {
                        if(cityItem == id) {
                            resolve(cityItem);
                        }
                    });
                }
            });
        } catch(err) {
            reject({
                name: 'ERROR_DATA',
                message: '查找数据失败'
            });
        }
    });
};

const Cities = mongoose.model('Cities',citySchema);

Cities.findOne((err, data) => {
    if(!data) {
        Cities.create({data: cityData});
    }
});

export default Cities;

编写城市控制器

在web->controller->v1文件夹下,创建city.js文件,具体代码如下:

/**
 * Created by admin on 2017/9/20 0020.
 */
'use strict';
import Cities from '../../models/v1/city';
import pinyin from 'pinyin';
import AddressComponent from '../../prototype/addressComponent';

class CityHandle extends AddressComponent {
    //构造函数
    constructor() {
        super();
        this.getCity = this.getCity.bind(this);
        this.getExactAddress = this.getExactAddress.bind(this);
        this.pois = this.pois.bind(this);
    }

    //获取城市
    async getCity(req, res, next) {
        const type = req.query.type;
        let cityInfo;
        try{
            switch(type) {
                case "guess":
                    const city = await this.getCityName(req);
                    cityInfo = await Cities.cityGuess(city);
                    break;
                case "hot":
                    cityInfo = await Cities.cityHot();
                    break;
                case "group":
                    cityInfo = await Cities.cityGroup();
                    break;
                default:
                    res.send({
                        name:'ERROR_QUERY_TYPE',
                        message:'参数错误'
                    });
                    return;
            }
            res.send(cityInfo);
        } catch(err) {
            res.send({
                name: 'ERROR_DATA',
                message: '获取数据失败'
            })
        }
    }

    //根据编号ID获取城市
    async getCityById(req, res, next) {
        const cityid = req.params.id;
        if(isNaN(cityid)) {
            res.send({
                name:'ERROR_PARAMS_TYPE',
                message:'参数错误'
            });
            return;
        }
        try{
            const cityInfo = await Cities.getCityById(cityid);
            res.send(cityInfo);
        } catch(err) {
            res.send({
                name:'ERROR_DATA',
                message:'获取数据失败'
            })
        }
    };

    //获取城市名称
    async getCityName(req) {
        let cityInfo;
        try{
            cityInfo = await this.guessPosition(req);
        } catch(err) {
            console.error('获取IP位置信息失败',err);
            res.send({
                name: 'ERROR_DATA',
                message: '获取数据失败'
            });
            return;
        }
        //汉字转换成拼音
        const pinyinArr = pinyin(cityInfo.city, {
            style:pinyin.STYLE_NORMAL,
        });
        let cityName = '';
        pinyinArr.forEach(item => {
            cityName += item[0];
        });
        return cityName;
    }

    //获取地址
    async getExactAddress(req, res, next) {
        try{
            const position = await this.geocoder(req);
            res.send(position);
        } catch(err) {
            console.log('获取精确位置失败');
            res.send({
                name:'ERROR_DATA',
                message:'获取精确位置失败'
            })
        }
    }

    async pois(req, res, next) {
        const geohash = req.params.geohash;
        try{
            if(geohash.indexOf(',') == -1) {
                throw new Error('参数错误');
            }
        } catch(err) {
            console.log('参数错误');
            res.send({
                status: 0,
                type: 'ERROR_PARAMS',
                message: '参数错误'
            });
            return;
        }
        const poisArr = geohash.split(',');
        try{
            const result = await this.getpois(poisArr[0], poisArr[1]);
            const address = {
                address: result.result.address,
                city: result.result.address_component.province,
                geohash,
                latitude: poisArr[0],
                longitude: poisArr[1],
                name: result.result.formatted_addresses.recommend,
            };
            res.send(address);
        } catch(err) {
            console.log('getpois返回信息失败');
            res.send({
                status: 0,
                type: 'ERROR_DATA',
                message: '获取数据失败'
            })
        }
    }
}

export default new CityHandle();

编写路由信息

在routes文件夹创建v1.js文件,这里对应的模型、控制器里的信息,具体代码如下:

import express from 'express';
import CityHandle from '../web/controller/v1/city';

const baseHandle = new BaseComponent();
const router = express.Router();

router.get('/cities', CityHandle.getCity);
router.get('/cities/:id', CityHandle.getCityById);
router.get('/exactaddress', CityHandle.getExactAddress);
router.post('/addimg/:type', baseHandle.uploadImg);

export default router;

然后我们在routes->index.js里面把v1的内容加进去,具体如下:

'use strict';
import admin from './admin';
import statis from './statis';
import v1 from './v1';
export default app => {
    app.use('/admin',admin);
    app.use('/statis',statis);
    app.use('/v1', v1);
};

下面我们就来测试我们的模块是否可行。打开目录下的cmd.dat,这个文件在一开始我们就创建过了,不懂的朋友可以看看第二节。
我们打开cmd.dat,然后输入“npm run dev”,显示如下:

nodeJS开发一套完整的项目(6、省市县模块)_第1张图片
项目启动页

然后在地址栏里输入 http://127.0.0.1:3000/v1/cities?type=hot,这是获取热点城市接口,数据显示如图:

nodeJS开发一套完整的项目(6、省市县模块)_第2张图片

其他的接口大家可以试试看,在此就不一一演示了。

相关章节

nodeJS开发一套完整的项目(1、基础配置)
nodeJS开发一套完整的项目(2、相关模块介绍)
nodeJS开发一套完整的项目(3、数据库链接和项目启动)
nodeJS开发一套完整的项目(4、编写底层功能模块)
nodeJS开发一套完整的项目(5、开发用户模块)
为了更好的服务大家,请加入我们的技术交流群:(511387930),同时您也可以扫描下方的二维码关注我们的公众号,每天我们都会分享经验,谢谢大家。

nodeJS开发一套完整的项目(6、省市县模块)_第3张图片

你可能感兴趣的:(nodeJS开发一套完整的项目(6、省市县模块))