订单管理
文章目录
一 基础页面
1.1 顶部子组件:选择表单
//子组件一:选择表单
class FilterForm extends React.Component {
render() {
const {getFieldDecorator} = this.props.form;
return (
<Form layout="inline">
<FormItem label="城市">
{
getFieldDecorator('city_id')(
<Select
style={{width: 100}}
placeholder="全部"
>
<Option value="">全部</Option>
<Option value="1">北京</Option>
<Option value="2">天津</Option>
<Option value="3">深圳</Option>
</Select>
)
}
</FormItem>
<FormItem label="订单时间">
{
getFieldDecorator('start_time')(
<DatePicker
placeholder="请选择开始时间"
showTime
format="YYYY-MM-DD HH:mm:ss"
/>
)
}
</FormItem>
<FormItem>
{
getFieldDecorator('end_time')(
<DatePicker
placeholder="请选择结束时间"
showTime
format="YYYY-MM-DD HH:mm:ss"
/>
)
}
</FormItem>
<FormItem label="订单状态">
{
getFieldDecorator('order_status')(
<Select
style={{width: 150}}
placeholder="全部"
>
<Option value="">全部</Option>
<Option value="1">进行中</Option>
<Option value="2">行程结束</Option>
</Select>
)
}
</FormItem>
<FormItem>
<Button type="primary" style={{margin: '0 20px'}}>查询</Button>
<Button>重置</Button>
</FormItem>
</Form>
);
}
}
FilterForm = Form.create({})(FilterForm);
1.2 数据接口
1. 订单数据接口
/order/list
{
"code": 0,
"msg": "",
"result": {
"page|1-9": 1,
"page_size": 10,
"total": 85,
"page_count": 9,
"item_list|10": [{
"id|+1": 2959165,
"order_sn": /T180[0-9]{6}/,
"bike_sn": "800116090",
"user_id": 908352,
"user_name": "@cname",
"mobile": /1[0-9]{10}/,
"distance": 2000,
"total_time": 4000,
"status|1-2": 1,
"start_time": "@datetime",
"end_time": "@datetime",
"total_fee": 1000,
"user_pay": 300
}]
},
}
同城市管理:调用this.requestList()
,默认请求接口数据
2. 结束订单接口
/order/ebike_info
{
"code": '0',
"result": {
"id": 27296,
"bike_sn": "800116116",
"battery": 100,
"start_time": "@datetime",
"location": "北京市海淀区奥林匹克公园"
}
}
3. 结束成功接口
/order/finish_order
{
"code": '0',
"result": 'Ok'
}
1.3 实例代码
1. 结束订单按钮
监听onClick事件,调用this.handleConfirm()显示确认结束弹框
> > > <Button type="primary" style={{marginLeeft: 10}} onClick={this.handlConfirm}>结束订单</Button> > > > ```javascript > // 订单结束确认 > handleConfirm = () => { > let item = this.state.selectedItem; > if (!item) { > Modal.info({ > title: '信息', > content: '请先选择一条订单进行结束' > }); > return; > } > > axios.ajax({ > url: '/order/ebike_info', > data: { > params: { > orderId: item.id > } > } > }).then((res) => { > if (res.code == 0) { > this.setState({ > orderInfo: res.result, > orderConfirmVisble: true, > }); > } > } > ); > }; > ``` > ``` > ``` > ```
2. 确认取消
打开Modal弹框,显示要取消的订单信息
<Modal
title="结束订单"
visible={this.state.orderConfirmVisble}
onCancel={() => {
this.setState({
orderConfirmVisble: false
});
}}
onOk={this.handleFinishOrder}
width={600}
>
<OpenCityForm {...this.state.orderInfo} />
</Modal>
...
class OpenCityForm extends React.Component {
render() {
return (...)
}
OpenCityForm = Form.create({})(OpenCityForm);
3. 结束订单
onOk事件调用this.handleFinishOrder()
// 结束订单
handleFinishOrder = () => {
let item = this.state.selectedItem;
axios.ajax({
url: '/order/finish_order',
data: {
params: {
orderId: item.id
}
}
}).then((res) => {
if (res.code == 0) {
message.success('订单结束成功');
this.setState({
orderConfirmVisble: false
});
this.requestList();
}
});
};
// src/pages/order/index.js
import React from 'react';
import {Card, Table, Form, Modal, Button, message, Input, Icon, Select, DatePicker,} from 'antd';
import axios from './../../axios/index';
import Utils from './../../utils/utils';
const FormItem = Form.Item;
const Option = Select.Option;
export default class Order extends React.Component {
state = {
orderInfo:{},
orderConfirmVisble: false
};
params = {
page: 1
};
componentDidMount() {
this.requestList();
}
// 默认请求我们的接口数据
requestList = () => {
let _this = this;
axios.ajax({
url: '/order/list',
data: {
params: {
page: this.params.page
}
}
}).then((res) => {
let list = res.result.item_list.map((item, index) => {
item.key = index;
return item;
});
this.setState({
list: list,
pagination: Utils.pagination(res, (current) => {
_this.params.page = current;
_this.requestList();
})
});
});
};
// 订单结束确认
handleConfirm = () => {
let item = this.state.selectedItem;
if (!item) {
Modal.info({
title: '信息',
content: '请先选择一条订单进行结束'
});
return;
}
axios.ajax({
url: '/order/ebike_info',
data: {
params: {
orderId: item.id
}
}
}).then((res) => {
if (res.code == 0) {
this.setState({
orderInfo: res.result,
orderConfirmVisble: true
});
}
}
);
};
// 结束订单
handleFinishOrder = () => {
let item = this.state.selectedItem;
axios.ajax({
url: '/order/finish_order',
data: {
params: {
orderId: item.id
}
}
}).then((res) => {
if (res.code == 0) {
message.success('订单结束成功');
this.setState({
orderConfirmVisble: false
});
this.requestList();
}
});
};
onRowClick = (record, index) => {
let selectKey = [index];
this.setState({
selectedRowKeys: selectKey,
selectedItem: record
});
};
onSelectChange = (selectedRowKeys, selectedItem) => {
const record = selectedItem[0];
this.setState({
selectedRowKeys: selectedRowKeys,
selectedItem: record
});
};
render() {
const selectedRowKeys = this.state.selectedRowKeys;
const rowSelection = {
type: 'radio',
selectedRowKeys,
onChange: this.onSelectChange
};
const columns = [{
title: '订单编号',
dataIndex: 'order_sn'
}, {
title: '车辆编号',
dataIndex: 'bike_sn'
}, {
title: '用户名',
dataIndex: 'user_name'
}, {
title: '手机号',
dataIndex: 'mobile'
}, {
title: '里程',
dataIndex: 'distance',
render(distance) {
return (distance / 1000) + " " + "km";
}
}, {
title: '行程时长',
dataIndex: 'total_time'
}, {
title: '状态',
dataIndex: 'status',
render(status) {
return status == 1 ? '进行中' : '行程结束';
}
}, {
title: '开始时间',
dataIndex: 'start_time'
}, {
title: '结束时间',
dataIndex: 'end_time'
}, {
title: '订单金额',
dataIndex: 'total_fee'
}, {
title: '实付金额',
dataIndex: 'user_pay'
}];
//{...this.state.orderInfo}
// 这个用法 相当于 从state 中取出 orderInfo 这个对象, 然后将其(this.state.orderInfo)展开
// 在子组件 ,使用props进行解构
/*
* var a = {b:[{id: 27296, bike_sn: "800116116"},{name:"张三"}]}
* console.log(a.b) // => [0:{id: 27296, bike_sn: "800116116"},
* 1:{name:"张三"}
* ]
*
* console.log(...a.b) // {id: 27296, bike_sn: "800116116"}
* {name:"张三"}
*/
return (
<div>
<Card>
<FilterForm/>
</Card>
<Card style={{marginTop: 10}}>
<Button type="primary">订单详情</Button>
<Button type="primary" style={{marginLeft: 20}} onClick={this.handleConfirm}>结束详情</Button>
</Card>
<div className="content-wrap">
<Table
bordered
columns={columns}
dataSource={this.state.list}
pagination={this.state.pagination}
rowSelection={rowSelection}
onRow={(record, index) => {
return {
onClick: () => {
this.onRowClick(record, index);
}
};
}}
/>
</div>
<Modal
title="结束订单"
visible={this.state.orderConfirmVisble}
onCancel={() => {
this.setState({
orderConfirmVisble: false
});
}}
onOk={this.handleFinishOrder}
width={600}
>
<OpenCityForm {...this.state.orderInfo} />
</Modal>
</div>
);
}
}
//子组件一:选择表单
class FilterForm extends React.Component {
render() {
const {getFieldDecorator} = this.props.form;
return (
<Form layout="inline">
<FormItem label="城市">
{
getFieldDecorator('city_id')(
<Select
style={{width: 100}}
placeholder="全部"
>
<Option value="">全部</Option>
<Option value="1">北京</Option>
<Option value="2">天津</Option>
<Option value="3">深圳</Option>
</Select>
)
}
</FormItem>
<FormItem label="订单时间">
{
getFieldDecorator('start_time')(
<DatePicker
placeholder="请选择开始时间"
showTime
format="YYYY-MM-DD HH:mm:ss"
/>
)
}
</FormItem>
<FormItem>
{
getFieldDecorator('end_time')(
<DatePicker
placeholder="请选择结束时间"
showTime
format="YYYY-MM-DD HH:mm:ss"
/>
)
}
</FormItem>
<FormItem label="订单状态">
{
getFieldDecorator('order_status')(
<Select
style={{width: 150}}
placeholder="全部"
>
<Option value="">全部</Option>
<Option value="1">进行中</Option>
<Option value="2">行程结束</Option>
</Select>
)
}
</FormItem>
<FormItem>
<Button type="primary" style={{margin: '0 20px'}}>查询</Button>
<Button>重置</Button>
</FormItem>
</Form>
);
}
}
FilterForm = Form.create({})(FilterForm);
//子组件二:开通城市
class OpenCityForm extends React.Component {
render() {
// console.log(this.props); // => {form: {…}, id: 27296, bike_sn: "800116116", battery: 100, start_time: "1972-07-26 03:08:22", …}
const {bike_sn, battery,start_time,location} = this.props;
const formItemLayout = {
labelCol: {
span: 5
},
wrapperCol: {
span: 19
}
};
return (
<Form>
<FormItem label="车辆编号" {...formItemLayout}>
{bike_sn}
</FormItem>
<FormItem label="剩余电量" {...formItemLayout}>
{battery + "%"}
</FormItem>
<FormItem label="行程开始时间" {...formItemLayout}>
{start_time}
</FormItem>
<FormItem label="当前位置" {...formItemLayout}>
{location}
</FormItem>
</Form>
);
}
}
OpenCityForm = Form.create({})(OpenCityForm);
二 订单详情(基础信息)
2.1 跳转详情页
1. 订单详情
按钮监听onClick事件
pages->order->index.js中:【订单详情】按钮监听onClick事件,调用this.openOrderDetail(),跳转路由
// 订单详情页
openOrderDetail = () => {
let item = this.state.selectedItem;
if (!item) {
Modal.info({
title: '信息',
content: '请先选择一条订单'
});
return;
}
// 通过window.open 进行路由的跳转
window.open('/#/common/order/detail/' + item.id,'_blank')
};
关键:window.open('/#/common/order/detail/' + item.id,'_blank')
2. 编写公共代码
src目录下:新建common.js,类似admin.js编写项目公共结构代码,负责路由详情页展示
// src/common.js
import React from "react";
import {Row, Col} from "antd";
import Header from "./components/Header";
import './style/common.less';
export default class Common extends React.Component {
render() {
return (
<div>
<Row className="simple-page">
<Header menuType="second"/>
</Row>
<Row className="content">
{this.props.children}
</Row>
</div>
);
}
}
通过menuType
:控制显示header组件的不同样式(components->header->index.js)
3. 实例代码
// src/components/Header/index.js
import React from 'react';
/*
Header组件 分两部分建立两行Row
第一行是用户的个人信息(这里以后要通过变量传输进来)
* */
import {Row, Col} from "antd";
import './index.less'
import Util from '../../utils/utils'//导入公共机制
import axios from "../../axios";//引入axios组件
export default class Header extends React.Component {
...
render() {
// 取出menuType 用作二级导航(父组件Common.js传来)
const menuType = this.props.menuType;
return (
<div className="header">
<Row className="header-top">
{
menuType?
<Col span="6" className="logo">
<img src="/assets/logo-ant.svg" alt=""/>
<span>IMooc 通用管理系统</span>
</Col>:''
}
<Col span={menuType?18:24}>
<span>欢迎,{this.state.userName}</span>
<a href="#">退出</a>
</Col>
</Row>
{
menuType?'':<Row className="breadcrumb">
<Col span="4" className="breadcrumb-title">
首页
</Col>
<Col span="20" className="weather">
<span className="date">{this.state.sysTime}</span>
<span className="weather-img">
<img src={this.state.dayPictureUrl} alt=""/>
</span>
<span className="weather-detail">
{this.state.weather}
{/*{this.state.date}*/}
</span>
</Col>
</Row>
}
</div>
);
}
}
4. 相关CSS样式
CSS样式
// src/components/Header/index.less
@import "./../../style/default.less";
.header {
background-color:@colorM ;
.header-top {
height: 60px;
line-height: 60px;
padding: 0 20px;
text-align: right;
.logo{
line-height: 60px;
text-align: left;
font-size: 18px;
img{
height: 40px;
vertical-align: middle;
}
span{
margin-left: 5px;
}
};
a {
margin-left: 40px;
}
}
.breadcrumb {
height: 40px;
line-height: 40px;
text-align: right;
padding: 0 20px;
border-top: 1px solid #f9c700;
.breadcrumb-title {
text-align: center;
font-size: @fontC;
&:after{
position: absolute;
content: '';
left: 83px;
top: 39px;
border-top: 9px solid @colorM;
border-left: 12px solid transparent;
border-right: 12px solid transparent;
}
}
.weather {
text-align: right;
font-size: 14px;
.date {
margin-right: 10px;
vertical-align: middle;
}
.weather-img{
img{
height: 15px;
}
}
.weather-detail{
margin-left: 5px;
vertical-align: middle;
}
}
}
}
// common 页面简单头
.simple-page{
.header-top{
background:#1890ff;
color:@colorM;
}
}
//引入pages->order->detail.less
5. router 组件
router.js
中:引入Common组件,使用的render方法定义嵌套路由
<Route path="/common" render={() => {
return <Common>
<Route path="/common/order/detail/:orderId" component={Login}/>
</Common>
}}
/>
2.2 订单详情基础信息
获取订单详情基础信息
1. 订单详情数据接口
/order/detail
{
"code": '0',
"msg": '',
"result": {
"status": 2,
"order_sn": "T1803244422704080JGJI",
"bike_sn": "802410001",
"mode|1-2": 1,
"start_location": "北京市昌平区回龙观东大街",
"end_location": "北京市海淀区奥林匹克公园",
"city_id": 1,
"mobile": "13597482075",
"user_name": "@cname",
"distance": 10000,
"bike_gps": "116.398806,40.008637",
"start_time": 1521865027000,
"end_time": 1521865251000,
"total_time": 224,
"position_list": [{
"lon": 116.361221,
"lat": 40.043776
}, {
"lon": 116.363736,
"lat": 40.038086
}, {
"lon": 116.364599,
"lat": 40.036484
}, {
"lon": 116.373438,
"lat": 40.03538
}, {
"lon": 116.377966,
"lat": 40.036263
}, {
"lon": 116.379762,
"lat": 40.03654
}, {
"lon": 116.38084,
"lat": 40.033225
}, {
"lon": 116.38084,
"lat": 40.029413
}, {
"lon": 116.381343,
"lat": 40.021291
}, {
"lon": 116.381846,
"lat": 40.015821
}, {
"lon": 116.382637,
"lat": 40.008084
}, {
"lon": 116.398806,
"lat": 40.008637
}],
"area": [{
"lon": "116.274737",
"lat": "40.139759",
"ts": null
},
{
"lon": "116.316562",
"lat": "40.144943",
"ts": null
},
{
"lon": "116.351631",
"lat": "40.129498",
"ts": null
},
{
"lon": "116.390582",
"lat": "40.082481",
"ts": null
},
{
"lon": "116.38742",
"lat": "40.01065",
"ts": null
},
{
"lon": "116.414297",
"lat": "40.01181",
"ts": null
},
{
"lon": "116.696242",
"lat": "39.964035",
"ts": null
},
{
"lon": "116.494498",
"lat": "39.851306",
"ts": null
},
{
"lon": "116.238086",
"lat": "39.848647",
"ts": null
},
{
"lon": "116.189454",
"lat": "39.999418",
"ts": null
},
{
"lon": "116.244646",
"lat": "39.990574",
"ts": null
},
{
"lon": "116.281441",
"lat": "40.008703",
"ts": null
},
{
"lon": "116.271092",
"lat": "40.142201",
"ts": null
},
{
"lon": "116.271092",
"lat": "40.142201",
"ts": null
}
],
"area_list": null,
"npl_list": [{
"id": 8265,
"name": "北辰世纪中心-a座",
"city_id": 1,
"type": 3,
"status": 0,
"map_point": "116.39338796444|40.008120315215;116.39494038009002|40.008177258745;116.39496911688|40.006268094213;116.39512457763|40.004256795877;116.39360214742|40.004222412241;116.39357190147|40.005075745782;116.39351397873|40.005836165232;116.39338796444|40.008120315215",
"map_point_array": ["116.39338796444|40.008120315215", "116.396053|40.008273", "116.396448|40.006338", "116.396915|40.004266", "116.39192|40.004072", "116.391525|40.004984", "116.391381|40.005924", "116.391166|40.007913"],
"map_status": 1,
"creator_name": "赵程程",
"create_time": 1507863539000
}]
}
}
2. 获取url参数orderId
componentDidMount()中获取url参数orderId:调用this.getDetailInfo(orderId)获取订单详情数据
componentDidMount() {
// 通过this.props.match.params. 取路由中的id(router-v4)
let orderId = this.props.match.params.orderId;
if (orderId) {
this.getDetailInfo(orderId);
}
}
getDetailInfo = (orderId) => {
axios.ajax({
url: '/order/detail',
data: {
params: {
orderId: orderId
}
}
}).then((res) => {
if (res.code == 0) {
this.setState({
orderInfo: res.result,
});
}
});
};
关键:this.props.match.params.
参数 详情:React获取url参数—this.props.match
3. 实例代码
// src/pages/order/detail.js
import React from 'react';
import {Card} from 'antd';
import axios from './../../axios/index';
import './detail.less';
export default class OrderDetail extends React.Component {
state = {};
componentDidMount() {
// 通过this.props.match.params. 取路由中的id(router-v4)
let orderId = this.props.match.params.orderId;
if (orderId) {
this.getDetailInfo(orderId);
}
}
getDetailInfo = (orderId) => {
axios.ajax({
url: '/order/detail',
data: {
params: {
orderId: orderId
}
}
}).then((res) => {
if (res.code == 0) {
this.setState({
orderInfo: res.result,
});
}
});
};
render() {
const info = this.state.orderInfo || {};//如果orderInfo 为空,返回 {}
return (
<div>
<Card>
<div id="OrderDetailMap"></div>
<div className="detail-items">
<div className="item-title">基础信息</div>
<ul className="detail-form">
<li>
<div className="detail-form-left">用车模式</div>
<div className="detail-form-content">{info.mode == 1 ? '服务区' : '停车点'}</div>
</li>
<li>
<div className="detail-form-left">订单编号</div>
<div className="detail-form-content">{info.order_sn}</div>
</li>
<li>
<div className="detail-form-left">车辆编号</div>
<div className="detail-form-content">{info.bike_sn}</div>
</li>
<li>
<div className="detail-form-left">用户姓名</div>
<div className="detail-form-content">{info.user_name}</div>
</li>
<li>
<div className="detail-form-left">手机号码</div>
<div className="detail-form-content">{info.mobile}</div>
</li>
</ul>
</div>
<div className="detail-items">
<div className="item-title">行驶轨迹</div>
<ul className="detail-form">
<li>
<div className="detail-form-left">行程起点</div>
<div className="detail-form-content">{info.start_location}</div>
</li>
<li>
<div className="detail-form-left">行程终点</div>
<div className="detail-form-content">{info.end_location}</div>
</li>
<li>
<div className="detail-form-left">行程里程</div>
<div className="detail-form-content">{info.distance / 1000}公里</div>
</li>
</ul>
</div>
</Card>
</div>
);
}
}
三 订单详情(地图)
具体使用查看百度地图api网址:http://lbsyun.baidu.com/index.php?title=jspopular/guide/widget
地图实现步骤
- 创建ak(account key) , 加载百度地图sdk
- 地图初始化
- 添加地图控件
- 绘制用户行驶路线
- 绘制服务区地图
0. 代码格式
// src/pages/order/detail.js
import React from 'react';
import {Card} from 'antd';
import axios from './../../axios/index';
import './detail.less';
export default class OrderDetail extends React.Component {
state = {};
componentDidMount() {...}
getDetailInfo = (orderId) => {...};
// 初始化地图
renderMap = (result) => {
this.map = new window.BMap.Map('orderDetailMap');
// 添加地图控件
this.addMapControl();
// 调用路线图绘制方法
this.drawBikeRoute(result.position_list);
// 调用服务区绘制方法
this.drawServiceArea(result.area);
};
// 添加地图控件
addMapControl = () => {...};
// 绘制用户的行驶路线
// 需要坐标点(positionList)做参数
drawBikeRoute = (positionList) => {...}
// 绘制服务区
drawServiceArea = (positionList) => {...};
render() {
const info = this.state.orderInfo || {};//如果orderInfo 为空,返回 {}
return (
<div>
...
</div>
);
}
}
1. 创建ak
获取到Ak 值后就可以调用百度地图的服务了?
引入模块: 当没有npm 包时,需要使用src 引入script标签这样(如:引入 bootstrap…等)
拷贝src链接 到public目录下
<script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=您的密钥"/>
注: 在引入第三方模块时,常遇到,变量定义找不到
这时,使用 window. 变量名 , 使变量绑定到全局变量即可解决
react 是单页面程序
<!DOCTYPE html>
<html lang="en">
<!--public/index.html-->
<head>
...
<title>React App</title>
<!--通过script 标签引入外部模块-->
<script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=XmWWWzyDp7KbVdtcGKgDqAc8XKgTxGIG"/>
</head>
<body>
...
</body>
</html>
2. 地图初始化
// 初始化地图
renderMap = ()=>{
this.map = new window.BMap.Map('orderDetailMap');//new BMap.Map('orderDetailMap',,{enableMapClick:false});地图无法点击
this.map.centerAndZoom('北京',11);
this.addMapControl();
};
3. 地图控件
// 添加地图控件
addMapControl = () => {
let map = this.map;
map.addControl(new window.BMap.ScaleControl({anchor:window.BMAP_ANCHOR_TOP_RIGHT}));
map.addControl(new window.BMap.NavigationControl({anchor:window.BMAP_ANCHOR_TOP_RIGHT}))
};
控件 | 类名 | 简介 |
---|---|---|
抽象基类 | Control | 所有控件均继承此类的方法、属性。通过此类您可实现自定义控件 |
平移缩放控件 | NavigationControl | PC端默认位于地图左上方,它包含控制地图的平移和缩放的功能。移动端提供缩放控件,默认位于地图右下方 |
缩略地图 | OverviewMapControl | 默认位于地图右下方,是一个可折叠的缩略地图 |
比例尺 | ScaleControl | 默认位于地图左下方,显示地图的比例关系 |
地图类型 | MapTypeControl | 默认位于地图右上方 |
版权 | CopyrightControl | 默认位于地图左下方 |
定位 | GeolocationControl | 针对移动端开发,默认位于地图左下方 |
控制控件位置
初始化控件时,可提供一个可选参数,其中的anchor和offset属性共同控制控件在地图上的位置。 anchor表示控件的停靠位置,即控件停靠在地图的哪个角。当地图尺寸发生变化时,控件会根据停靠位置的不同来调整自己的位置。
anchor值 | 位置说明 |
---|---|
BMAP_ANCHOR_TOP_LEFT | 表示控件定位于地图的左上角 |
BMAP_ANCHOR_TOP_RIGHT | 表示控件定位于地图的右上角 |
BMAP_ANCHOR_BOTTOM_LEFT | 表示控件定位于地图的左下角 |
BMAP_ANCHOR_BOTTOM_RIGHT | 表示控件定位于地图的右下角 |
控件位置偏移
offset
4. 行驶路线
- 绘制 起/终 坐标点
- 将 起点/终点 用折线进行连接
// 绘制用户的行驶路线
// 需要坐标点(positionList)做参数
drawBikeRoute = (positionList) => {
let map = this.map; // 通过map 拿到地图的对象
let startPoint = '';
let endPoint = '';
if (positionList.length > 0) {
let first = positionList[0]; // 第一个坐标点
let last = positionList[positionList.length - 1]; // 第一个坐标点
startPoint = new window.BMap.Point(first.lon, first.lat); // arr.lon 经度 arr.lat 纬度
// 创建起始坐标点的图标(Icon),设置Icon图标的大小(宽:36,高:42)
let startIcon = new window.BMap.Icon('/assets/start_point.png', new window.BMap.Size(36, 42), {
// 控件中图片的大小
imageSize: new window.BMap.Size(36, 42),
// 停靠的位置
anchor: new window.BMap.Size(36, 42)
});
// 创建标注
// 定义Marker 将图标放入页面(坐标点,图标)
let startMarker = new window.BMap.Marker(startPoint, {icon: startIcon});
// 将标注添加到地图中
this.map.addOverlay(startMarker);
endPoint = new window.BMap.Point(last.lon, last.lat);
let endIcon = new window.BMap.Icon('/assets/end_point.png', new window.BMap.Size(36, 42), {
// 控件中图片的大小
imageSize: new window.BMap.Size(36, 42),
// 停靠的位置
anchor: new window.BMap.Size(36, 42)
});
let endMarker = new window.BMap.Marker(endPoint, {icon: endIcon});
this.map.addOverlay(endMarker);
// 连接路线图
let trackPoint = [];
for (let i = 0; i < positionList.length; i++) {
// 换了个名称,用point 代替positionList 显得简洁
let point = positionList[i];
// 将接口返回的坐标点,转换为百度地图api 需要的坐标点
trackPoint.push(new window.BMap.Point(point.lon, point.lat));
// 画折线
// 线的颜色,宽度,透明度
let polyline = new window.BMap.Polyline(trackPoint, {
strokeColor: '#1869AD',
strokeWeight: 3,
strokeOpacity: 1
});
this.map.addOverlay(polyline);
}
// 生成地图的中心点
this.map.centerAndZoom(endPoint, 11);
}
};
5. 绘制服务区
// 绘制服务区
drawServiceArea = (positionList) => {
// 连接路线图
let trackPoint = [];
for (let i = 0; i < positionList.length; i++) {
// 换了个名称,用point 代替positionList 显得简洁
let point = positionList[i];
// 将接口返回的坐标点,转换为百度地图api 需要的坐标点
trackPoint.push(new window.BMap.Point(point.lon, point.lat));
}
// 绘制服务区 fillColor 填充颜色
let polygon = new window.BMap.Polygon(trackPoint, {
strokeColor: '#CE0000',
strokeWeight: 4,
strokeOpacity: 1,
fillColor:'#ff8605',
fillOpacity:0.4
});
this.map.addOverlay(polygon);
};
6. 实例代码
// src/pages/order/detail.js
import React from 'react';
import {Card} from 'antd';
import axios from './../../axios/index';
import './detail.less';
export default class OrderDetail extends React.Component {
state = {};
componentDidMount() {
// 通过this.props.match.params. 取路由中的id(router-v4)
let orderId = this.props.match.params.orderId;
if (orderId) {
this.getDetailInfo(orderId);
}
}
getDetailInfo = (orderId) => {
axios.ajax({
url: '/order/detail',
data: {
params: {
orderId: orderId
}
}
}).then((res) => {
if (res.code == 0) {
this.setState({
orderInfo: res.result,
});
this.renderMap(res.result);
}
});
};
// 初始化地图
renderMap = (result) => {
this.map = new window.BMap.Map('orderDetailMap');//new BMap.Map('orderDetailMap',,{enableMapClick:false});地图无法点击
// this.map.centerAndZoom('北京', 11);
// 添加地图控件
this.addMapControl();
// 调用路线图绘制方法
this.drawBikeRoute(result.position_list); // 初始化完成绘制路线图
// 调用服务区绘制方法
this.drawServiceArea(result.area);
};
// 添加地图控件
addMapControl = () => {
let map = this.map;
map.addControl(new window.BMap.ScaleControl({anchor: window.BMAP_ANCHOR_TOP_RIGHT}));
map.addControl(new window.BMap.NavigationControl({anchor: window.BMAP_ANCHOR_TOP_RIGHT}));
};
// 绘制用户的行驶路线
// 需要坐标点(positionList)做参数
drawBikeRoute = (positionList) => {
let map = this.map; // 通过map 拿到地图的对象
let startPoint = '';
let endPoint = '';
if (positionList.length > 0) {
let first = positionList[0]; // 第一个坐标点
let last = positionList[positionList.length - 1]; // 第一个坐标点
startPoint = new window.BMap.Point(first.lon, first.lat); // arr.lon 经度 arr.lat 纬度
// 创建起始坐标点的图标(Icon),设置Icon图标的大小(宽:36,高:42)
let startIcon = new window.BMap.Icon('/assets/start_point.png', new window.BMap.Size(36, 42), {
// 控件中图片的大小
imageSize: new window.BMap.Size(36, 42),
// 停靠的位置
anchor: new window.BMap.Size(36, 42)
});
// 创建标注
// 定义Marker 将图标放入页面(坐标点,图标)
let startMarker = new window.BMap.Marker(startPoint, {icon: startIcon});
// 将标注添加到地图中
this.map.addOverlay(startMarker);
endPoint = new window.BMap.Point(last.lon, last.lat);
let endIcon = new window.BMap.Icon('/assets/end_point.png', new window.BMap.Size(36, 42), {
// 控件中图片的大小
imageSize: new window.BMap.Size(36, 42),
// 停靠的位置
anchor: new window.BMap.Size(36, 42)
});
let endMarker = new window.BMap.Marker(endPoint, {icon: endIcon});
this.map.addOverlay(endMarker);
// 连接路线图
let trackPoint = [];
for (let i = 0; i < positionList.length; i++) {
// 换了个名称,用point 代替positionList 显得简洁
let point = positionList[i];
// 将接口返回的坐标点,转换为百度地图api 需要的坐标点
trackPoint.push(new window.BMap.Point(point.lon, point.lat));
// 画折线
// 线的颜色,宽度,透明度
let polyline = new window.BMap.Polyline(trackPoint, {
strokeColor: '#1869AD',
strokeWeight: 3,
strokeOpacity: 1
});
this.map.addOverlay(polyline);
}
// 生成地图的中心点
this.map.centerAndZoom(endPoint, 11);
}
};
// 绘制服务区
drawServiceArea = (positionList) => {
// 连接路线图
let trackPoint = [];
for (let i = 0; i < positionList.length; i++) {
// 换了个名称,用point 代替positionList 显得简洁
let point = positionList[i];
// 将接口返回的坐标点,转换为百度地图api 需要的坐标点
trackPoint.push(new window.BMap.Point(point.lon, point.lat));
}
// 绘制服务区 fillColor 填充颜色
let polygon = new window.BMap.Polygon(trackPoint, {
strokeColor: '#CE0000',
strokeWeight: 4,
strokeOpacity: 1,
fillColor:'#ff8605',
fillOpacity:0.4
});
this.map.addOverlay(polygon);
};
render() {
const info = this.state.orderInfo || {};//如果orderInfo 为空,返回 {}
return (
<div>
<Card>
<div id="orderDetailMap" className='order-map'></div>
<div className="detail-items">
<div className="item-title">基础信息</div>
<ul className="detail-form">
<li>
<div className="detail-form-left">用车模式</div>
<div className="detail-form-content">{info.mode == 1 ? '服务区' : '停车点'}</div>
</li>
<li>
<div className="detail-form-left">订单编号</div>
<div className="detail-form-content">{info.order_sn}</div>
</li>
<li>
<div className="detail-form-left">车辆编号</div>
<div className="detail-form-content">{info.bike_sn}</div>
</li>
<li>
<div className="detail-form-left">用户姓名</div>
<div className="detail-form-content">{info.user_name}</div>
</li>
<li>
<div className="detail-form-left">手机号码</div>
<div className="detail-form-content">{info.mobile}</div>
</li>
</ul>
</div>
<div className="detail-items">
<div className="item-title">行驶轨迹</div>
<ul className="detail-form">
<li>
<div className="detail-form-left">行程起点</div>
<div className="detail-form-content">{info.start_location}</div>
</li>
<li>
<div className="detail-form-left">行程终点</div>
<div className="detail-form-content">{info.end_location}</div>
</li>
<li>
<div className="detail-form-left">行程里程</div>
<div className="detail-form-content">{info.distance / 1000}公里</div>
</li>
</ul>
</div>
</Card>
</div>
);
}
}