基于Express+vue+高德地图API实现的出行可视化APP
1.项目简介 1
1.1技术栈 1
1.2功能模块 1
1.2.1个人出行 1
1.2.2公共交通 2
1.2.3历史列表 2
1.2.4我的信息(未完成) 2
2.项目构建 2
2.1前端 2
2.2后端 3
3.系统设计 3
3.1项目配置 3
3.2路由转发 4
3.3请求拦截器 5
3.4正则验证规则 5
4.项目运行 6
5.项目截图 6
公共交通 7
历史列表 8
我的信息 9
6.小结 10
6.1项目简结 10
6.2过程总结 10
i. 实时定位,绘制出行轨迹(悦跑圈,已完成) 10
ii. 路线规划,规划路线绘制路径图(百度地图,已完成) 10
iii. 网约车,快车,专车,顺风车在线叫车(滴滴出行,未完成) 10
iv. 可视化分析,出行数据的可视化分析(已完成) 10
6.3难点总结 11
6.4补充 11
6.5更新 11
1.1技术栈
前端:移动端,vue全家桶,Mand组件库,Echarts.js,Scss
后端:Node,Express框架,高德地图API
数据库:Mysql
1.2功能模块
1.2.1个人出行
用户个人出行,不确定路程、目的地等信息,选择出行工具,点击开始,系统实时监听用户手机位置得到WGS84经纬度坐标(w3c HTML5 Geolocation地理定位标准),行程结束,记录本次出行信息,经纬度坐标转换GCJ-02坐标体系,通过高德地图提供三方API绘制出行轨迹。
1.2.2公共交通
用户确定出发地、目的地、交通工具,选择公共交通出行,用户输入位置关键字,选择合适出发/目的位置,选择乘坐交通工具,规划出行路线,选择某一条路线,确定后点击保存上传本次出行记录
1.2.3历史列表
按时间顺序查看所有出行的历史记录,可查看出行的详情信息、行程轨迹、路线规划
1.2.4我的信息
查看我的详情信息,通过出行数据分析得到的出行趋势折线图,与出行数据相关的数据分析图表,其他功能未写
2.项目构建
2.1前端
前端在 vue-cli3 基础上开发,在此之上根据项目需求对项目工程作出几点修改,前端代码在 view/ 文件夹中
移动端适配:之前做移动端开发一直使用手淘的分辨率适配方案,本项目根据大漠的《如何在Vue项目中使用vw实现移动端适配》,对移动端分辨率用webpack在工程中配置。
请求拦截器:在 view/src/request/ 中,基于 axios 提供的 interceptors 对所有ajax的请求和响应添加相应操作,如请求头添加,token添加,响应后台错误状态码的识别与报错;简单封装了下axios请求,主要为get,post两种。
导航守卫:在 view/src/router/ 中,做了全局导航守卫,未登录用户只能访问项目登录页面。
工具类:在 view/src/utils/ 中,对常用枚举值、全局组件注册、常用类封装等功能做模块化封装。
css样式:在 view/src/style/ 中,全局公共样式,初始化样式。
svg组件:在 view/src/icons/ 中,封装用于svg展示组件,用做小icon的展示,svg保存该文件夹中。
模块化:对路由与vuex做模块化封装。
地图:所有地图、地理信息、轨迹、路线规划功能有高德地图第三方API提供
2.2后端
使用 Node 的 express 框架,连接 Mysql 数据库,做数据接口开发,数据的增删改查与简单封装。
项目配置
const path = require('path')
function resolve (dir) {
return path.join(__dirname, './', dir)
}
module.exports = {
chainWebpack: config => {
//为src下文件配别名,不使用相对路径 config.resolve.alias
.set('@', resolve('src'))
.set('assets', resolve('src/assets'))
.set('components', resolve('src/components'))
.set('views', resolve('src/views'))
.set('icons', resolve('src/icons'))
.set('router', resolve('src/router'))
.set('utils', resolve('src/utils'))
.set('style', resolve('src/style'))
/** 设置处理svg的router,使svg可直接用名称调用,无需路径 */
// svg rule loader
const svgRule = config.module.rule('svg') // 找到svg-loader svgRule.uses.clear() // 清除已有的loader, 如果不这样做会添加在此loader之后 svgRule.exclude.add(/node_modules/) // 正则匹配排除node_modules目录 svgRule // 添加svg新的loader处理
.test(/\.svg$/)
.use('svg-sprite-loader')
.loader('svg-sprite-loader')
.options({
symbolId: 'icon-[name]'
})
},
publicPath: './',
/** 开发环境代理 */
devServer: {
open: true,
proxy: {
'/api': {
target: 'http://localhost:3000',
ws: true,
changeOrigin: true,
pathRequires: {
'^/api': ''
}
}
}
}
}
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var indexRouter = require('./routes/index');
var userRouter = require('./routes/user');
var tripRouter = require('./routes/trip');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', indexRouter);
app.use('/user', userRouter);
app.use('/trip', tripRouter);
//catch 404 and forward to error handler app.use(function(req, res, next) {
next(createError(404)); });
//error handler
app.use(function(err, req, res, next) {
//set locals, only providing error in development res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
//render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;