【共享单车】—— React后台管理系统开发手记:城市管理和订单管理

时间:2022-08-29 04:59:06

前言:以下内容基于React全家桶+AntD实战课程的学习实践过程记录。最终成果github地址:https://github.com/66Web/react-antd-manager,欢迎star。


一、城市管理

【共享单车】—— React后台管理系统开发手记:城市管理和订单管理

  • pages->city->index.js:对应路由/admin/city
  • 顶部子组件一:选择表单
    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('mode')(
    <Select
    style={{ width: 120 }}
    placeholder="全部"
    >
    <Option value="">全部</Option>
    <Option value="1">指定停车点模式</Option>
    <Option value="2">禁停区模式</Option>
    </Select>
    )
    }
    </FormItem>
    <FormItem label="营运模式">
    {
    getFieldDecorator('op_mode')(
    <Select
    style={{ width: 80 }}
    placeholder="全部"
    >
    <Option value="">全部</Option>
    <Option value="1">自营</Option>
    <Option value="2">加盟</Option>
    </Select>
    )
    }
    </FormItem>
    <FormItem label="加盟商授权状态">
    {
    getFieldDecorator('auth_status')(
    <Select
    style={{ width: 100 }}
    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(){
    const formItemLayout = {
    labelCol:{ //label标签占据列数
    span:5
    },
    wrapperCol:{ //Form表单占据列数
    span:19
    }
    }
    const { getFieldDecorator } =this.props.form;
    return (
    <Form layout="horizontal">
    <FormItem label="选择城市" {...formItemLayout}>
    {
    getFieldDecorator('city_id',{
    initialValue:'1'
    })(
    <Select style={{ width: 100 }}>
    <Option value="">全部</Option>
    <Option value="1">北京市</Option>
    <Option value="2">天津市</Option>
    </Select>
    )
    }
    </FormItem>
    <FormItem label="营运模式" {...formItemLayout}>
    {
    getFieldDecorator('op_mode', {
    initialValue: '1'
    })(
    <Select style={{ width: 100 }}>
    <Option value="1">自营</Option>
    <Option value="2">加盟</Option>
    </Select>
    )
    }
    </FormItem>
    <FormItem label="用车模式" {...formItemLayout}>
    {
    getFieldDecorator('use_mode', {
    initialValue: '1'
    })(
    <Select style={{ width: 100 }}>
    <Option value="1">指定停车点</Option>
    <Option value="2">禁停区</Option>
    </Select>
    )
    }
    </FormItem>
    </Form>
    );
    }
    }
    OpenCityForm = Form.create({})(OpenCityForm);
  • Easy Mock城市管理的数据接口:/open_city

    {
    "code": 0,
    "msg": "",
    "list": {
    "item_list|10": [{
    "id|+1": 1,
    "name": "@city",
    "mode|1-2": 1,
    "op_mode|1-2": 1,
    "franchisee_id": 77,
    "franchisee_name": "松果自营",
    "city_admins|1-2": [{
    "user_name": "@cname",
    "user_id|+1": 10001
    }],
    "open_time": "@datetime",
    "sys_user_name": "@cname",
    "update_time": 1546580667000
    }]
    },
    page: 1,
    page_size: 10,
    total: 20
    }
  1. componentDidMount()中:调用this.requestList(),默认请求接口数据
    componentDidMount(){
    this.requestList();
    } // 默认请求我们的接口数据
    requestList = ()=>{
    let _this = this;
    axios.ajax({
    url: '/open_city',
    data:{
    params:{
    page:this.params.page
    }
    }
    }).then((res)=>{
    let list = res.list.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();
    })
    })
    })
    }  
  • Easy Mock城市开通的数据接口:/city/open

    {
    "code": 0,
    "list": "开通成功"
    }
  1. 【开通城市】按钮:监听onClick事件,调用this.handleOpenCity()显示弹框

    state = {
    list:[],
    isShowOpenCity:false //默认隐藏弹框
    } // 开通城市
    handleOpenCity = ()=>{
    this.setState({
    isShowOpenCity:true
    })
    }
  2. Modal关键属性visible控制弹框的显示隐藏,关键事件onOk调用this.handleSubmit()提交表单信息

     <Modal
    title="开通城市"
    visible={this.state.isShowOpenCity}
    onCancel={()=>{
    this.setState({
    isShowOpenCity:false
    })
    }}
    onOk={this.handleSubmit}
    >
    <OpenCityForm wrappedComponentRef={(inst)=>{this.cityForm = inst;}}/>
    </Modal>

    wrappedComponentRef属性:拿到表单中的信息对象inst,通过this.cityForm存到state中

    【共享单车】—— React后台管理系统开发手记:城市管理和订单管理

  3. 城市开通信息提交

    // 城市开通提交
    handleSubmit = ()=>{
    let cityInfo = this.cityForm.props.form.getFieldsValue();
    console.log(cityInfo);
    axios.ajax({
    url:'/city/open',
    data:{
    params:cityInfo
    }
    }).then((res)=>{
    if(res.code === 0){
    message.success('开通成功');
    this.setState({
    isShowOpenCity:false
    })
    this.requestList();
    }
    })
    }
  • 实例代码
    import React from 'react';
    import { Card, Button, Table, Form, Select, Modal, message } from 'antd';
    import axios from './../../axios/index';
    import Utils from './../../utils/utils';
    const FormItem = Form.Item;
    const Option = Select.Option; export default class City extends React.Component{ state = {
    list:[],
    isShowOpenCity:false //默认隐藏弹框
    }
    params = {
    page:1
    }
    componentDidMount(){
    this.requestList();
    } // 默认请求我们的接口数据
    requestList = ()=>{
    let _this = this;
    axios.ajax({
    url: '/open_city',
    data:{
    params:{
    page:this.params.page
    }
    }
    }).then((res)=>{
    let list = res.list.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();
    })
    })
    })
    } // 开通城市
    handleOpenCity = ()=>{
    this.setState({
    isShowOpenCity:true
    })
    }
    // 城市开通提交
    handleSubmit = ()=>{
    let cityInfo = this.cityForm.props.form.getFieldsValue();
    console.log(cityInfo);
    axios.ajax({
    url:'/city/open',
    data:{
    params:cityInfo
    }
    }).then((res)=>{
    if(res.code === 0){
    message.success('开通成功');
    this.setState({
    isShowOpenCity:false
    })
    this.requestList();
    }
    })
    }
    render(){
    const columns = [
    {
    title:'城市ID',
    dataIndex:'id'
    }, {
    title: '城市名称',
    dataIndex: 'name'
    }, {
    title: '用车模式',
    dataIndex: 'mode',
    render(mode){
    return mode === 1 ?'停车点':'禁停区';
    }
    }, {
    title: '营运模式',
    dataIndex: 'op_mode',
    render(op_mode) {
    return op_mode === 1 ? '自营' : '加盟';
    }
    }, {
    title: '授权加盟商',
    dataIndex: 'franchisee_name'
    }, {
    title: '城市管理员',
    dataIndex: 'city_admins',
    render(arr){ //处理数组类型
    return arr.map((item)=>{
    return item.user_name;
    }).join(',');
    }
    }, {
    title: '城市开通时间',
    dataIndex: 'open_time'
    }, {
    title: '操作时间',
    dataIndex: 'update_time',
    render: Utils.formateDate //格式化时间戳
    }, {
    title: '操作人',
    dataIndex: 'sys_user_name'
    }
    ]
    return (
    <div>
    <Card>
    <FilterForm />
    </Card>
    <Card style={{marginTop:10}}>
    <Button type="primary" onClick={this.handleOpenCity}>开通城市</Button>
    </Card>
    <div className="content-wrap">
    <Table
    bordered
    columns={columns}
    dataSource={this.state.list}
    pagination={this.state.pagination}
    />
    </div>
    <Modal
    title="开通城市"
    visible={this.state.isShowOpenCity}
    onCancel={()=>{
    this.setState({
    isShowOpenCity:false
    })
    }}
    onOk={this.handleSubmit}
    >
    <OpenCityForm wrappedComponentRef={(inst)=>{this.cityForm = inst;}}/>
    </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('mode')(
    <Select
    style={{ width: 120 }}
    placeholder="全部"
    >
    <Option value="">全部</Option>
    <Option value="1">指定停车点模式</Option>
    <Option value="2">禁停区模式</Option>
    </Select>
    )
    }
    </FormItem>
    <FormItem label="营运模式">
    {
    getFieldDecorator('op_mode')(
    <Select
    style={{ width: 80 }}
    placeholder="全部"
    >
    <Option value="">全部</Option>
    <Option value="1">自营</Option>
    <Option value="2">加盟</Option>
    </Select>
    )
    }
    </FormItem>
    <FormItem label="加盟商授权状态">
    {
    getFieldDecorator('auth_status')(
    <Select
    style={{ width: 100 }}
    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(){
    const formItemLayout = {
    labelCol:{ //label标签占据列数
    span:5
    },
    wrapperCol:{ //Form表单占据列数
    span:19
    }
    }
    const { getFieldDecorator } =this.props.form;
    return (
    <Form layout="horizontal">
    <FormItem label="选择城市" {...formItemLayout}>
    {
    getFieldDecorator('city_id',{
    initialValue:'1'
    })(
    <Select style={{ width: 100 }}>
    <Option value="">全部</Option>
    <Option value="1">北京市</Option>
    <Option value="2">天津市</Option>
    </Select>
    )
    }
    </FormItem>
    <FormItem label="营运模式" {...formItemLayout}>
    {
    getFieldDecorator('op_mode', {
    initialValue: '1'
    })(
    <Select style={{ width: 100 }}>
    <Option value="1">自营</Option>
    <Option value="2">加盟</Option>
    </Select>
    )
    }
    </FormItem>
    <FormItem label="用车模式" {...formItemLayout}>
    {
    getFieldDecorator('use_mode', {
    initialValue: '1'
    })(
    <Select style={{ width: 100 }}>
    <Option value="1">指定停车点</Option>
    <Option value="2">禁停区</Option>
    </Select>
    )
    }
    </FormItem>
    </Form>
    );
    }
    }
    OpenCityForm = Form.create({})(OpenCityForm);

      

二、订单管理

【共享单车】—— React后台管理系统开发手记:城市管理和订单管理

  • 顶部子组件:选择表单
    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 showTime format="YYYY-MM-DD HH:mm:ss"/>
    )
    }
    </FormItem>
    <FormItem style={{marginLeft: -10}}>
    {
    getFieldDecorator('end_time')(
    <DatePicker style={{marginLeft: 5}} showTime format="YYYY-MM-DD HH:mm:ss"/>
    )
    }
    </FormItem>
    <FormItem label="订单状态">
    {
    getFieldDecorator('status')(
    <Select
    style={{ width: 80 }}
    placeholder="全部"
    >
    <Option value="">全部</Option>
    <Option value="1">进行中</Option>
    <Option value="2">结束行程</Option>
    </Select>
    )
    }
    </FormItem>
    <FormItem>
    <Button type="primary" style={{margin:'0 5px'}}>查询</Button>
    <Button>重置</Button>
    </FormItem>
    </Form>
    );
    }
    }
    FilterForm = Form.create({})(FilterForm);
  • Easy Mock订单数据接口:/order/list
    {
    "code": 0,
    "msg": "",
    "list": {
    "item_list|10": [{
    "id": 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
    }]
    },
    "page|1-9": 1,
    page_size: 10,
    total: 85,
    page_count: 9
    }

    同城市管理:调用this.requestList(),默认请求接口数据  

  • Easy Mock结束订单信息数据接口:/order/ebike_info
    {
    "code": 0,
    "list": {
    "id": 27296,
    "bike_sn": "800116116",
    "battery": 100,
    "start_time": "@datetime",
    "location": "西虹市海淀区桃花公园"
    }
    }
  • Easy Mock结束订单成功数据接口:/order/finish_order

    {
    "code": 0,
    "list": "ok"
    }
  1. 【结束订单】按钮:监听onClick事件,调用this.handleConfirm()显示确认结束弹框

    <Button type="primary" style={{marginLeeft: 10}} onClick={this.handlConfirm}>结束订单</Button>
    //订单结束确认
    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.list,
    orderConfirmVisible: true
    })
    }
    })
    }
  2. 确认取消:打开Modal弹框,显示要取消的订单信息

     <Modal
    title="结束订单"
    visible={this.state.orderConfirmVisible}
    onCancel={() => {
    this.setState({
    orderConfirmVisible: false
    })
    }}
    onOk={this.handleFinishOrder}
    width={600}>
    <Form layout="horizontal">
    <FormItem label="车辆编号" {...formItemLayout}>
    {this.state.orderInfo.bike_sn}
    </FormItem>
    <FormItem label="剩余电量" {...formItemLayout}>
    {this.state.orderInfo.battery + '%'}
    </FormItem>
    <FormItem label="行程开始时间" {...formItemLayout}>
    {this.state.orderInfo.start_time}
    </FormItem>
    <FormItem label="当前位置" {...formItemLayout}>
    {this.state.orderInfo.location}
    </FormItem>
    </Form>
    </Modal>
  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({
    orderConfirmVisible: false
    })
    this.requestList();
    }
    })
    }
  • 实例代码:

    import React from 'react'
    import { Card, Button, Table, Form, Select, Modal, message, 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: {},
    orderConfirmVisible: false
    }
    params = {
    page:1
    } componentDidMount(){
    this.requestList();
    } requestList = () => {
    let _this = this;
    axios.ajax({
    url: '/order/list',
    data: {
    params: {
    page: this.params.page
    }
    }
    }).then((res) => {
    if(res.code === 0){
    let list = res.list.item_list.map((item, index) => {
    item.key = index;
    return item;
    });
    this.setState({
    list:list,
    selectedRowKeys: [],//重置
    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.list,
    orderConfirmVisible: 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({
    orderConfirmVisible: false
    })
    this.requestList();
    }
    })
    }
    onRowClick = (record, index) => {
    let selectKey = [index];
    this.setState({
    selectedRowKeys: selectKey,
    selectedItem: record
    })
    } //订单详情页
    openOrderDetail = () => {
    let item = this.state.selectedItem;
    if(!item){
    Modal.info({
    title: '信息',
    content: '请先选择一条订单'
    })
    return;
    }
    window.open(`/#/common/order/detail/${item.id}`,'_blank')
    } render(){
    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'
    },
    {
    title: '开始时间',
    dataIndex: 'start_time'
    },
    {
    title: '结束时间',
    dataIndex: 'end_time'
    },
    {
    title: '订单金额',
    dataIndex: 'total_fee'
    },
    {
    title: '实付金额',
    dataIndex: 'user_pay'
    }
    ]
    const formItemLayout = {
    labelCol: {
    span: 5
    },
    wrapperCol: {
    span: 19
    }
    }
    const selectedRowKeys = this.state.selectedRowKeys;
    const rowSelection = {
    type: 'radio',
    selectedRowKeys
    } return (
    <div>
    <Card>
    <FilterForm />
    </Card>
    <Card style={{marginTop:10}}>
    <Button type="primary" onClick={this.openOrderDetail}>订单详情</Button>
    <Button type="primary" style={{marginLeeft: 10}} onClick={this.handlConfirm}>结束订单</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.orderConfirmVisible}
    onCancel={() => {
    this.setState({
    orderConfirmVisible: false
    })
    }}
    onOk={this.handleFinishOrder}
    width={600}>
    <Form layout="horizontal">
    <FormItem label="车辆编号" {...formItemLayout}>
    {this.state.orderInfo.bike_sn}
    </FormItem>
    <FormItem label="剩余电量" {...formItemLayout}>
    {this.state.orderInfo.battery + '%'}
    </FormItem>
    <FormItem label="行程开始时间" {...formItemLayout}>
    {this.state.orderInfo.start_time}
    </FormItem>
    <FormItem label="当前位置" {...formItemLayout}>
    {this.state.orderInfo.location}
    </FormItem>
    </Form>
    </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 showTime format="YYYY-MM-DD HH:mm:ss"/>
    )
    }
    </FormItem>
    <FormItem style={{marginLeft: -10}}>
    {
    getFieldDecorator('end_time')(
    <DatePicker style={{marginLeft: 5}} showTime format="YYYY-MM-DD HH:mm:ss"/>
    )
    }
    </FormItem>
    <FormItem label="订单状态">
    {
    getFieldDecorator('status')(
    <Select
    style={{ width: 80 }}
    placeholder="全部"
    >
    <Option value="">全部</Option>
    <Option value="1">进行中</Option>
    <Option value="2">结束行程</Option>
    </Select>
    )
    }
    </FormItem>
    <FormItem>
    <Button type="primary" style={{margin:'0 5px'}}>查询</Button>
    <Button>重置</Button>
    </FormItem>
    </Form>
    );
    }
    }
    FilterForm = Form.create({})(FilterForm);

      

三、订单详情

【共享单车】—— React后台管理系统开发手记:城市管理和订单管理

  • 跳转详情页
  1. pages->order->index.js中:【订单详情】按钮监听onClick事件,调用this.openOrderDetail(),跳转路由
     //订单详情页
    openOrderDetail = () => {
    let item = this.state.selectedItem;
    if(!item){
    Modal.info({
    title: '信息',
    content: '请先选择一条订单'
    })
    return;
    }
    window.open(`/#/common/order/detail/${item.id}`,'_blank')
    }

    关键:window.open(`/#/common/order/detail/${item.id}`,'_blank')

  2. src目录下:新建common.js,类似admin.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)

    //其它代码
    render() {
    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>LJQ 通用管理系统</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-detail">晴转多云</span>
    </Col>
    </Row>
    }
    </div>
    )
    }

    CSS样式:

    //style->common.less
    ul,li{
    list-style: none;
    }
    .clearfix{
    &::after{
    content:'';
    clear: both;
    display: block;
    visibility: hidden;
    }
    }
    .content{
    padding: 20px
    } //components->header->index.less
    //.common 页面简单头
    .simple-page{
    .header-top{
    background: #1890ff;
    color: @colorM;
    }
    .ant-form, .ant-col-12, .weather{
    display: none;
    }
    } //引入pages->order->detail.less
  3. router.js中:引入Common组件,使用<Route />的render方法定义嵌套路由

    <Route path="/common" render={() =>
    <Common>
    <Route path="/common/order/detail/:orderId" component={OrderDetail} />
    </Common>
    }/>
  • 获取订单详情基础信息

  1. Easy Mock订单详情数据接口:/order/detail 

    {
    "code": 0,
    "msg": "",
    "list": {
    "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": 1546580667000,
    "end_time": 1546608995000,
    "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. componentDidMount()中获取url参数orderId:调用this.getDetailInfo(orderId)获取订单详情数据

    componentDidMount(){
    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.list
    })
    this.renderMap(res.list);
    }
    })
    }

    关键:this.props.match.params.参数 详情:【React获取url参数—this.props.match

  • 实例代码

    import React from 'react';
    import { Card } from 'antd';
    import axios from '../../axios';
    import './detail.less'; export default class Order extends React.Component{ state = {} componentDidMount(){
    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.list
    })
    this.renderMap(res.list);
    }
    })
    } //初始化地图
    renderMap = (list) => {
    this.map = new window.BMap.Map('orderDetailMap');
    // this.map.centerAndZoom('北京', 11)
    //添加地图控件
    this.addMapControl();
    //调用路线图绘制方法
    this.drawBikeRoute(list.position_list);
    //调用服务区绘制方法
    this.drawServiceArea(list.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 }));
    } //绘制用户行驶路线图
    drawBikeRoute = (positionList) => {
    let map = this.map;
    let startPoint = '';
    let endPoint = '';
    if(positionList.length > 0){
    //起点
    let first = positionList[0];
    startPoint = new window.BMap.Point(first.lon, first.lat);
    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)
    }) let startMarker = new window.BMap.Marker(startPoint, {icon: startIcon});
    this.map.addOverlay(startMarker); //终点
    let last = positionList[positionList.length-1];
    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++){
    let point = positionList[i]
    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++){
    let point = positionList[i]
    trackPoint.push(new window.BMap.Point(point.lon, point.lat))
    } 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 || {};
    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}Km</div>
    </li>
    </ul>
    </div>
    </Card>
    </div>
    );
    }
    }  

注:项目来自慕课网