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

react

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


一、城市管理

  • 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中

  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);

      

二、订单管理

  •  顶部子组件:选择表单

    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);

      

三、订单详情

  • 跳转详情页

  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>

    );

    }

    }  


注:项目来自慕课网

以上是 【共享单车】—— React后台管理系统开发手记:城市管理和订单管理 的全部内容, 来源链接: utcz.com/z/383775.html

回到顶部