效果图:
该实例是在antd pro 的项目环境下修改实现:https://pro.ant.design/docs/getting-started-cn
添加订单页面:
订单列表页面:
antd pro这个脚手架是使用分层架构,来层层实现数据传递,pages存放页面,从页面获取数据传递到models层,然后再models中调用services的异步请求接口数据的方法。
订单管理的代码有点多,分如下几个页面:
先说说添加订单的页面实现:
pages:
OrderManager就是pages中的一个页面文件夹,modal里面是存放点击编辑弹出来的组件(在OrderTable中调用),models中的order.js就是订单管理的model层了(里面写的effects异步请求方法在OrderList和PengingList中通过dispatch调用),AddOrEditOrder.js是添加页面(在配置路由中调用),不要被名字迷惑了。OrderFilter.js是查询组件(在OrderList和PengingList中调用),OrderList.js是未处理的订单列表(在OrderTable中调用),PendingList.js是已处理的订单列表(在OrderTable中调用),OrderTable.js是Table的column(在OrderList和PengingList中调用),OrderTab.js是切换未处理订单和已处理订单的的组件(在配置路由中调用)。如看不懂描述请见谅,移步看代码。
代码(不是项目全部代码,仅供参考,项目不打算在GitHub上公开,请参考如下代码,如有问题希望指出):
OrderTab.js:
import { Tabs, Row, Col } from 'antd';
import React, { PureComponent } from 'react';
import OrderList from './OrderList';
import PendingList from './PendingList';
import PageHeaderWrapper from '../../components/PageHeaderWrapper';
export default class OrderTab extends PureComponent {
render() {
const headerAction = null;
return (
<PageHeaderWrapper title='' action={headerAction}>
<Tabs defaultActiveKey="default" size="large">
<Tabs.TabPane tab="未处理订单" key="default" style={{ marginTop: '1em' }}>
<OrderList />
</Tabs.TabPane>
<Tabs.TabPane tab="已处理订单" key="second">
<PendingList />
</Tabs.TabPane>
</Tabs>
</PageHeaderWrapper>
);
}
}
OrderTable.js:
import React, { Fragment } from 'react';
import _ from 'lodash';
import { Icon, Popconfirm } from 'antd';
import moment from 'moment';
import EditModal from './modals/EditOrder'
export const DATE_TIME_FORMAT = 'YYYY-MM-DD HH:mm:ss';
export const DATE_FORMAT = 'YYYY-MM-DD';
function getDateTimeString(msTimeOrDate) {
if (msTimeOrDate === null) return null;
if (msTimeOrDate && typeof msTimeOrDate === 'object') {
if ('format' in msTimeOrDate && typeof msTimeOrDate.format === 'function')
return msTimeOrDate.format(DATE_TIME_FORMAT);
if (msTimeOrDate instanceof Date) return moment(msTimeOrDate).format(DATE_TIME_FORMAT);
}
// @ts-ignore
return moment(new Date(msTimeOrDate)).format(DATE_TIME_FORMAT);
}
function newColumn(title, dataIndex, render = undefined ) {
return { title, dataIndex, render, key: dataIndex };
}
export default function getOrderColumns(props,eventHandler) {
const { onMarkOrder,onEditOrder,clearError,onEditSubmit} = eventHandler;
const isDeal = {
false: "已处理",
true: "未处理",
}
return [
// newColumn('订单编号', 'uuid'),
newColumn('客户名称', 'username'),
newColumn('电话', 'phone'),
newColumn('鞋子类型','types'),
newColumn('取鞋时间','take_time'),
newColumn('送鞋时间', 'send_time'),
newColumn('洗鞋费用', 'money'),
newColumn('数量','sum'),
// newColumn('地址','address'),
// newColumn('备注','textarea'),
newColumn('下单时间', 'time', it => {
const m = moment(it);
return (
<span title={getDateTimeString(m)}>
{m.fromNow()}
</span>
);
}),
newColumn('订单状态','status', it => (<span style={{ color: '#ff0000'}}>{it}</span>)),
{
align: 'right',
title: '操作',
key: 'op',
render: it => {
return(
<Fragment>
{
it.status === '订单中' ? (
// 父组件
<EditModal
onShowAsync={clearError}
onOk={onEditSubmit}
>
<a
style={{ marginLeft: 50 }}
onClick={onEditOrder.bind(this, _.get(it,'uuid',''))} >
<Icon type="edit" /> 编辑
</a>
</EditModal>
): null
}
{
it.status === "订单中" ? (
<a
style={{ color: "d9d9d9", marginRight: 10 }}
onClick={onMarkOrder.bind(this, _.get(it, 'uuid', ''))} >
<Icon type="check-circle" /> 标记已处理
</a>
) : null
}
<Popconfirm
title={<span>确定删除该订单?<br /></span>}
okType="danger"
onConfirm={eventHandler.onDeleteOrder.bind(null, it)}
okText="确认删除"
cancelText="取消"
>
<a style={{ color: '#FC1E39', marginLeft: 20 }}>
<Icon type="delete" /> 删除
</a>
</Popconfirm>
</Fragment>
)
}
}
];
}
OrderList.js:
import React ,{ PureComponent,Fragment} from 'react';
import _ from 'lodash';
import { connect } from 'dva';
import moment from 'moment';
import { Form, Table, Card ,Input, Row, Col, Button,Badge,message} from 'antd';
import getOrderColumns from './OrderTable';
import { easyRouteTo } from '../../utils/easyDispatch';
function newRequiredRule(msg) {
return { required: true, message: msg };
}
@connect(({ order, loading }) => ({
order,
loading: loading.models.order,
}))
@Form.create()
class OrderList extends PureComponent {
constructor(props) {
super(props);
this.state = {
error: '',
formValues: {},
}
}
componentDidMount() {
this.query();
}
onDeleteOrder(orderList) {
if (!orderList) return;
this.clearError();
console.warn('page uuid',orderList.uuid);
const { dispatch } = this.props;
dispatch({
type: 'order/fetchDeleteOeder',
payload: {uuid: orderList.uuid },
});
this.query();
}
clearError() { this.setState({ error: '' }); }
query() {
this.clearError();
const { dispatch } = this.props;
dispatch({
type: 'order/fetchOederList',
});
}
onMarkOrder(uuid) {
const { dispatch } = this.props;
console.warn('page uuid',uuid)
dispatch({
type: 'order/fetchonMarkOrder',
payload: { uuid }
});
}
handleSearch =e => {
e.preventDefault();
const { dispatch, form } = this.props;
form.validateFields((err, fieldsValue) => {
if (err) return;
this.setState({
formValues: { ...fieldsValue },
});
dispatch({
type: 'order/fetchqueryByNameOrPhone',
payload: {...fieldsValue },
})
});
}
onEditSubmit(values) {
const { dispatch } = this.props;
this.clearError();
const sendEditValues = Object.assign({},values);
sendEditValues.take_time = values.take_time.format('YYYY-MM-DD HH:mm');
sendEditValues.send_time = values.send_time.format('YYYY-MM-DD HH:mm');
console.warn('AAAAAAAAAAAAAAAAAAAAAAAA',sendEditValues);
dispatch({
type: 'order/fetchOrderEdit',
payload: sendEditValues,
});
message.success('修改成功');
this.query();
}
handleFormReset = () => {
const { form, dispatch } = this.props;
form.resetFields();
this.setState({
formValues: {}
});
}
//
onEditOrder(uuid) {
const { dispatch } = this.props;
dispatch({
type: 'order/fetchOrderbyUUID',
payload: uuid
})
}
render() {
const { order,loading, form}= this.props;
const { error } = this.state;
const orderList = Array.isArray(order.orderList) > 0 ? order.orderList : [];
const tableColumns = getOrderColumns(
{ order },
{
//onEditOrder: it => easyRouteTo(this, `/order/basic-list/${it.uuid}`),
onDeleteOrder: this.onDeleteOrder.bind(this),
onMarkOrder: this.onMarkOrder.bind(this),
onEditOrder: this.onEditOrder.bind(this),
onEditSubmit: this.onEditSubmit.bind(this),
clearError: this.clearError.bind(this),
});
const submitText = (
<Col md={6} sm={8}>
<Button type="primary" htmlType="submit">查询</Button>
<Button style={{ marginLeft: 10 }} onClick={this.handleFormReset}>重置</Button>
</Col>
);
const renderOrderFilter = (
<Form onSubmit={this.handleSearch} layout="inline" style={{ marginBottom: 30}}>
<Row gutter={{ md: 8, lg: 24, xl: 48 }}>
<Col md={6} sm={24}>
<Form.Item label="名字筛选">
{form.getFieldDecorator('username', {
rules: [
{
// required: false,
message: '请输入要查询的客户名字!',
}
]
})(<Input placeholder="客户名字关键字" />)}
</Form.Item>
</Col>
<Col md={6} sm={24}>
<Form.Item label="电话筛选">
{form.getFieldDecorator('phone', {
rules: [
{
// required: false,
message: '请输入查询的电话号码!',
}
]
})(<Input placeholder="客户电话关键字" />)}
</Form.Item>
</Col>
{submitText}
<Col md={4} sm={24}>
<span style={{ color: '#e60000'}}>未处理订单总数: <Badge count={orderList.length} /> 请及时处理</span>
</Col>
</Row>
</Form>
);
return(
<Card bordered={false}>
{renderOrderFilter}
<Table
loading={loading}
columns={tableColumns}
rowKey={record => record.uuid}
dataSource={orderList}
pagination={{"defaultPageSize":10, showQuickJumper: true }}
size="middle"
// bordered
expandedRowRender={record => <div><p style={{ margin: 0 }}>备注:{record.textarea}</p><br /><p>地址:{record.address}</p></div>}
components={this.components}
/>
</Card>
)
}
}
export default OrderList;
PengingList.js:
import React ,{ PureComponent } from 'react';
import _ from 'lodash';
import { connect } from 'dva';
import { Form, Table, Card ,Input, Row, Col, Button,Badge} from 'antd';
import getOrderColumns from './OrderTable';
import { easyRouteTo } from '../../utils/easyDispatch';
@connect(({ order, loading }) => ({
order,
loading: loading.models.order,
}))
@Form.create()
class PendingList extends PureComponent {
constructor(props) {
super(props);
this.state = {
error: '',
formValues: {},
}
}
componentDidMount() {
this.query();
}
onDeleteOrder(pendList) {
if (!pendList) return;
this.clearError();
console.warn('page uuid',pendList.uuid);
const { dispatch } = this.props;
dispatch({
type: 'order/fetchDeleteOeder',
payload: {uuid: pendList.uuid },
}).then((response) => {
if (response === "删除成功"){
this.query();
}
});
}
clearError() { this.setState({ error: '' }); }
query() {
this.clearError();
const { dispatch } = this.props;
dispatch({
type: 'order/fetchPengingList',
});
}
onSubmit() {
this.props.form.validateFields((error, values) => {
if (error) return;
this.setState({ error: ''});
const queryValues = Object.assign({}, values);
console.warn("query got the data", queryValues);
this.props.dispatch({
type: 'order/fetchqueryByNameOrPhone',
payload: { ...values },
})
})
}
handleSearch =e => {
e.preventDefault();
const { dispatch, form } = this.props;
form.validateFields((err, fieldsValue) => {
if (err) return;
this.setState({
formValues: { ...fieldsValue },
});
console.warn('1111111111111111',fieldsValue);
// if (fieldsValue === '') {
// message.error()
// }
dispatch({
type: 'order/fetchqueryByNameOrPhone',
payload: {...fieldsValue },
})
})
}
handleFormReset = () => {
const { form, dispatch } = this.props;
form.resetFields();
this.setState({
formValues: {}
});
}
render() {
const { order,loading,form}= this.props;
const { error } = this.state;
const pendList = Array.isArray(order.pendList) > 0 ? order.pendList : [];
const tableColumns = getOrderColumns(
{ order },
{
onEditOrder: it => easyRouteTo(this, `/order/basic-list/${it.uuid}`),
onDeleteOrder: this.onDeleteOrder.bind(this),
});
const submitText = (
<Col md={4} sm={8}>
<Button icon="check" type="primary" htmlType="submit" onClick={ev => { ev.preventDefault(); this.onSubmit();}}>查询</Button>
<Button style={{ marginLeft: 10 }} onClick={this.handleFormReset}>重置</Button>
</Col>
);
const renderOrderFilter = (
<Form onSubmit={this.handleSearch} layout="inline" style={{ marginBottom: 30}}>
<Row gutter={{ md: 8, lg: 24, xl: 48 }}>
<Col md={8} sm={24}>
<Form.Item label="名字筛选">
{form.getFieldDecorator('username', {
rules: [
{
required: false,
message: '请输入要查询的客户名字!',
}
]
})(<Input placeholder="客户名字关键字" />)}
</Form.Item>
</Col>
<Col md={8} sm={24}>
<Form.Item label="电话筛选">
{form.getFieldDecorator('phone', {
rules: [
{
required: false,
message: '请输入查询的电话号码!',
}
]
})(<Input placeholder="客户电话关键字" />)}
</Form.Item>
</Col>
{submitText}
<Col md={4} sm={24}>
<span style={{ color: '#e60000'}}>已处理订单总数:<Badge style={{ backgroundColor: '#52c41a' }} count={pendList.length} /></span>
</Col>
</Row>
</Form>
);
return(
<Card bordered={false}>
{renderOrderFilter}
<Table
loading={loading}
columns={tableColumns}
rowKey={record => record.uuid}
dataSource={pendList}
pagination={{"defaultPageSize":10, showQuickJumper: true }}
size="middle"
// bordered
expandedRowRender={record => <div><p style={{ margin: 0 }}>备注:{record.textarea}</p><br /><p>地址:{record.address}</p></div>}
components={this.components}
/>
</Card>
)
}
}
export default PendingList;
OrderFilter.js;
import React, { Fragment } from 'react';
import { Row, Col, Form, Select, Button, Input } from 'antd';
export default function renderOrderFilter ( form ) {
const submitText = '查询';
return (
<Fragment>
<Row gutter={16}>
<Col md={6} sm={24}>
<Form.Item label="名字筛选">
{form.getFieldDecorator('username', {
})(<Input placeholder="客户名字关键字" />)}
</Form.Item>
</Col>
<Col md={6} sm={24}>
<Form.Item label="电话筛选">
{form.getFieldDecorator('phone', {
})(<Input placeholder="客户电话关键字" />)}
</Form.Item>
</Col>
<Col md={4} sm={8}>
<Button type="primary" htmlType="submit">{submitText}</Button>
</Col>
</Row>
</Fragment>
);
}
AddOrder.js
import React ,{ Component } from 'react';
import _ from 'lodash';
import { connect } from 'dva';
import moment from 'moment';
import { Row, Col, Card, Form, Icon,Button, message, Alert,Badge, DatePicker, Input, Radio} from 'antd';
import PageHeaderWrapper from '../../components/PageHeaderWrapper';
import { easyRouteTo, easyDispatch } from '../../utils/easyDispatch';
import createFormItems from '../../utils/createFormItem';
const RadioGroup = Radio.Group;
const ButtonGroup = Button.Group;
const defaultGoBack = {
router: '/order/user-order',
title: '订单列表',
}
function newRequiredRule(msg) {
return { required: true, message: msg };
}
function newMaxLenRule(len, name) {
return { max: len, message: `${name} 不允许超过 ${len} 个字!` };
}
@connect(({ order, loading }) => ({
order,
isSaving: loading.effects['order/fetchcreateOrder'],
loading: loading.models.order,
}))
@Form.create()
class AddOrder extends Component {
constructor(props) {
super(props);
this.state = {
error: '',
value: '',
money: 0,
count: 0,
}
}
// 编辑订单
componentDidMount() {
const { dispatch } = this.props;
dispatch({
type: 'order/fetchShoesTypes',
});
}
// 添加订单
onSubmit() {
// const antdForm = this.props.form;
const { value, count, money } = this.state;
const { dispatch, form } = this.props;
form.validateFields((error, values) => {
if (error) return;
this.setState({ error: '' });
const sendValues = Object.assign({ }, values );
sendValues.take_time = values.take_time.format('YYYY-MM-DD HH:mm');
sendValues.send_time = values.send_time.format('YYYY-MM-DD HH:mm');
sendValues.types = value;
sendValues.sum = count;
sendValues.money = money * count;
dispatch({
type: 'order/fetchcreateOrder',
payload: sendValues,
});
});
message.success('下单成功');
easyRouteTo(this,defaultGoBack.router);
}
getEditOrderId() { return parseInt(_.get(this, 'props.match.params.uuid', ''), 10); }
onChange = e => {
this.setState({
value: e.target.value,
money: e.target.title,
})
}
increase = () => {
const count = this.state.count +1;
this.setState({ count });
}
decline = () => {
let count = this.state.count -1;
if (count < 0 ) {
count = 0;
}
this.setState({count})
}
render() {
const { order, isSaving } = this.props;
const shoesList = Array.isArray(order.shoesList) > 0 ? order.shoesList : [];
const { error ,money} = this.state;
const content = (
<div>
<Button
icon="left"
onClick={ev => { ev.preventDefault(); easyRouteTo(this,defaultGoBack.router); }}
>
{defaultGoBack.title}
</Button>
</div>
);
const extraContent = (
<Button
icon="check"
type="primary"
disabled={!!isSaving || !!error}
onClick={ev => { ev.preventDefault();this.onSubmit();}}
>
确认保存
</Button>
);
/** @type {AntdForm} */
const antdForm = this.props.form;
const { getFieldDecorator } = antdForm;
const form = createFormItems(antdForm);
return (
<PageHeaderWrapper title="" content={content} loading={isSaving} extraContent={extraContent}>
<Card title={<span><Icon type="file" /> 基础信息</span>} style={{ marginBottom: 30}}>
<Row gutter={16}>
<Col lg={6} md={12} sm={24}>
<Form.Item label="客户名称">
{form.input({
name: 'username', rules: [
newRequiredRule(`客户名称不允许为空`),
newMaxLenRule(255,`用户名称`),
],
})}
</Form.Item>
</Col>
<Col lg={6} md={12} sm={24}>
<Form.Item label="客户电话">
{form.input({
name: 'phone', rules: [
newRequiredRule(`客户电话不允许为空`),
]
})}
</Form.Item>
</Col>
<Col lg={6} md={12} sm={24}>
<Form.Item label="取鞋时间">
{getFieldDecorator('take_time', {
// initialValue: initialValues.expireDate,
rules: [{
validator: (__, value, cb) => {
if (!moment.isMoment(value)) return cb('请选择取鞋日期');
if (value.diff(moment()) < 0) return cb(`${value.format('YYYY-MM-DD')} 已经过去!`);
cb();
},
}],
})(
<DatePicker
style={{ width: '100%' }}
showTime={{ format:'HH:mm' }}
format="YYYY-MM-DD HH:mm"
placeholder="请选择有效期"
/>
)}
</Form.Item>
</Col>
<Col lg={6} md={12} sm={24}>
<Form.Item label="送鞋时间">
{getFieldDecorator('send_time', {
// initialValue: initialValues.expireDate,
rules: [{
validator: (__, value, cb) => {
if (!moment.isMoment(value)) return cb('请选择送鞋日期');
if (value.diff(moment()) < 0) return cb(`${value.format('YYYY-MM-DD')} 已经过去!`);
cb();
},
}],
})(
<DatePicker
style={{ width: '100%' }}
showTime={{ format:'HH:mm' }}
format="YYYY-MM-DD HH:mm"
placeholder="请选择有效期" />
)}
</Form.Item>
</Col>
</Row>
<Row gutter={16}>
<Col sm={24} md={12} lg={16}>
<Form.Item label="详细地址 (如:广东省/中山市/石岐区/电子科技大学中山学院北门)">
{form.input({
name: 'address', rules: [
newRequiredRule(`详细地址不能为空`),
newMaxLenRule(255, `详细地址`),
],
})}
</Form.Item>
</Col>
</Row>
<Row gutter={16}>
<Col sm={24}>
<Form.Item label="备注信息">
{form.input({
name: 'textarea',rules: [
// newRequiredRule(`说明信息不允许为空`),
newMaxLenRule(255, `说明信息`),
],
})}
</Form.Item>
</Col>
</Row>
</Card>
<Card title={<span><Icon type="picture" /> 鞋子信息</span>} bordered={false} loading={isSaving }>
<Row gutter={16}>
<Col sm={24} md={12}>
<Form.Item label="鞋子类型 / 洗鞋费用">
{getFieldDecorator('types', {
})(
<div>
<Row>
{
shoesList.map(item => (
<Col span={6} style={{ marginBottom: 50,marginRight: 50 }}>
<img src={item.images} alt="aa" style={{ width: 100, height: 100 ,marginRight: 200}} />
<RadioGroup onChange={this.onChange} value={this.state.value}>
<Radio value={item.types} key={item.uuid} title={item.money}>{item.types} {item.textarea} {item.money}{`元/双`}</Radio>
</RadioGroup>
</Col>
))
}
</Row>
</div>
)}
</Form.Item>
</Col>
</Row>
<Row gutter={16}>
<Col lg={12} md={12} sm={24}>
<div>
<span>请选择该鞋子的数量:</span>
<Badge count={this.state.count}>
<ButtonGroup>
<Button onClick={this.decline}>
<Icon type="minus" />
</Button>
<Button onClick={this.increase}>
<Icon type="plus" />
</Button>
</ButtonGroup>
</Badge>
</div>
</Col>
<Col lg={12} md={12} sm={24}>
<div>
<span>合计费用:</span>
{this.state.count * this.state.money }
</div>
</Col>
</Row>
</Card>
</PageHeaderWrapper>
)
}
}
export default AddOrder;
EditOrder.js
import _ from 'lodash';
import { connect } from 'dva';
import moment from 'moment';
import React, { Fragment } from 'react';
import { Row ,Col, Form, Input,Select, Upload,message, Icon,DatePicker,Badge,Button,Radio} from 'antd';
import FormSubmitModal from '../../../components/FormSubmitModal';
const RadioGroup = Radio.Group;
const ButtonGroup = Button.Group;
function newRequiredRule(msg) {
return { required: true, message: msg };
}
function beforeUpload(file) {
const isJPG = file.type === 'image/jpeg';
if (!isJPG) {
message.error('you can only upload JPG file');
}
const isLt2M = file.size / 1024 / 1024 < 2;
if ( !isLt2M) {
message.error('image must samller than 2MB');
}
return isJPG && isLt2M
}
function getBase64(img, callback) {
const reader = new FileReader();
reader.addEventListener('load', () => callback(reader.result));
reader.readAsDataURL(img);
}
@connect(({ order }) => ({
order,
}))
@Form.create()
class EditModal extends React.Component {
constructor(props) {
super(props);
this.state = {
error: '',
loading: false,
}
}
onSubmit(values, callback) {
const { onOk } = this.props;
onOk(Object.assign({}, values), callback);
}
handleChange = info => {
if(info.file.status === "uploading ") {
this.setState({ loading: true });
return;
}
if (info.file.status === 'done') {
getBase64(info.file.originFileObj, imageUrl =>
this.setState({
imageUrl,
loading:false,
}))
}
}
render() {
const { error, loading,imageUrl, } = this.state;
const { order,onShowAsync} = this.props;
const editingOrder = Object.assign({}, order.editingOrder);
const uploadButton = (
<div>
<Icon type={ loading ? 'loading' : 'plus'} />
<div className="ant-upload-text" style={{ marginTop: 8,color: '#666' }}>上传图片</div>
</div>
);
return (
// 子组件
<FormSubmitModal
title='编辑订单'
onOk={this.onSubmit.bind(this)}
onShowAsync={onShowAsync}
formProvider={form => (
<Fragment>
<Row gutter={8}>
<Col md={24}>
<Form.Item label="UUID">
{form.getFieldDecorator('uuid', {
initialValue: editingOrder.uuid,
})(
<Input disabled />
)}
</Form.Item>
</Col>
</Row>
<Row gutter={8}>
<Col md={12}>
<Form.Item label="客户名称">
{form.getFieldDecorator('username', {
initialValue: editingOrder.username,
rules: [
newRequiredRule(`客户名称不允许为空`),
]
})(
<Input placeholder="请输入客户名称" />
)}
</Form.Item>
</Col>
<Col md={12}>
<Form.Item label="客户电话">
{form.getFieldDecorator('phone', {
initialValue: editingOrder.phone,
rules: [
newRequiredRule(`客户电话不允许为空`)
]
})(
<Input placeholder="请输入客户电话" />
)}
</Form.Item>
</Col>
</Row>
<Row gutter={8}>
<Col md={12}>
<Form.Item label="取鞋时间">
{form.getFieldDecorator('take_time', {
rules: [{
validator: (__, value, cb) => {
if (!moment.isMoment(value)) return cb('取鞋时间不允许为空');
if (value.diff(moment()) < 0) return cb(`${value.format('YYYY-MM-DD HH:mm')} 已经过去!`);
cb();
},
},
]
})(
<DatePicker
style={{ width: '100%' }}
showTime={{ format:'HH:mm' }}
format="YYYY-MM-DD HH:mm"
placeholder="请重新选择有效的取鞋时间"
/>
)}
</Form.Item>
</Col>
<Col md={12}>
<Form.Item label="送鞋时间">
{form.getFieldDecorator('send_time', {
// initialValue: editingOrder.send_time,
rules: [{
validator: (__, value, cb) => {
if (!moment.isMoment(value)) return cb('送鞋时间不允许为空');
if (value.diff(moment()) < 0) return cb(`${value.format('YYYY-MM-DD')} 已经过去!`);
cb();
},
},
]
})(
<DatePicker
style={{ width: '100%' }}
showTime={{ format:'HH:mm' }}
format="YYYY-MM-DD HH:mm"
placeholder="请重新选择有效的送鞋时间"
/>
)}
</Form.Item>
</Col>
</Row>
<Row gutter={8}>
<Col sm={24}>
<Form.Item label="详细地址 (如:广东省/中山市/石岐区/电子科技大学中山学院北门)">
{form.getFieldDecorator('address', {
initialValue: editingOrder.address,
rules: [
newRequiredRule(`详细地址不允许为空`)
]
})(
<Input placeholder="请输入详细地址" />
)}
</Form.Item>
</Col>
</Row>
<Row gutter={8}>
<Col md={24}>
<Form.Item label="备注信息">
{form.getFieldDecorator('textarea', {
initialValue: editingOrder.textarea,
})(
<Input placeholder="请输入备注信息" />
)}
</Form.Item>
</Col>
</Row>
<Row gutter={8}>
<Col sm={24}>
<Form.Item label="鞋子类型">
{form.getFieldDecorator('types', {
initialValue: editingOrder.types,
})(
<Input disabled placeholder="不允许修改" />
)}
</Form.Item>
</Col>
</Row>
<Row gutter={8}>
<Col md={8}>
<Form.Item label="鞋子数量">
{form.getFieldDecorator('sum',{
initialValue: editingOrder.sum,
})(
<Input disabled placeholder="不允许修改" />
)}
</Form.Item>
</Col>
<Col md={8}>
<Form.Item label="合计费用">
{form.getFieldDecorator('money',{
initialValue: editingOrder.money,
})(
<Input disabled placeholder="不允许修改" />
)}
</Form.Item>
</Col>
</Row>
</Fragment>
)}
>
{this.props.children}
</FormSubmitModal>
);
}
}
export default EditModal;
models层:
order.js:
import { message } from 'antd';
import * as services from '../../../services/order';
import { shoesList } from '../../../services/shoes';
import { easyRouteTo } from '../../../utils/easyDispatch';
const defaultGoBack = {
router: '/order/user-order',
title: '订单列表',
}
export default {
namespace: 'order',
state: {
orderList: {},
pendList: {},
shoesList: {},
editingOrder: null
},
effects: {
// 未处理
*fetchOederList(_, { call, put }) {
const response = yield call(services.orderList);
yield put({
type: 'save',
payload: response,
});
},
// 已处理
*fetchPengingList(_, { call, put }) {
const response = yield call(services.pendedList);
yield put({
type: 'pend',
payload: response,
})
},
*fetchDeleteOeder({ payload }, { call }) {
const response = yield call(services.orderDelete, payload.uuid);
if (!response) return;
if (response.code !== 200 ) {
message.success('删除成功!');
} else {
message.error('删除失败!');
}
},
// 添加订单
*fetchcreateOrder({ payload }, {call}) {
const response = yield call(services.orderAdd(payload));
if (!response) return;
if (response.code !== 200) {
message.success('下单成功');
easyRouteTo(this,defaultGoBack.router);
} else {
message.error('下单失败');
}
},
*fetchonMarkOrder({payload}, {call}) {
const response = yield call(services.onMarkOrder,payload.uuid);
if (!response) return;
if (response.code !==200) {
message.success('已标记处理');
} else {
message.error('标记失败');
}
},
// 查询
*fetchqueryByNameOrPhone({ payload }, { call, put }) {
const response = yield call(services.queryByNameOrPhone, payload);
if (!response) return;
if (response === []) {
message.error('查无此人');
} else {
message.success('查询成功');
}
yield put({
type: 'searchList',
payload: response,
})
},
*fetchShoesTypes(_, { call, put }) {
const response = yield call(shoesList);
yield put({
type: 'shoesList',
payload: response,
});
},
*fetchOrderbyUUID({ payload }, { put,call }) {
const response = yield call(services.searchbyUUID,payload);
if (!response) return;
yield put({
type: 'gotEditOrder',
payload: response,
})
},
*fetchOrderEdit({ payload }, {call}) {
console.warn("BBBBBBBBBBBBBBBBBBBBBBB",payload);
const response = yield call(services.orderEdit(payload));
if (!response) return;
if (response === '修改成功') {
message.success('修改成功');
// easyRouteTo(this,defaultGoBack.router);
} else {
message.error('修改失败');
}
}
},
reducers: {
save( state, { payload }) {
return {
...state,
orderList: payload
}
},
pend( state, { payload }) {
return {
...state,
pendList: payload,
}
},
shoesList(state, { payload }) {
return {
...state,
shoesList: payload,
}
},
searchList(state, { payload }) {
return {
...state,
orderList: payload,
}
},
gotEditOrder( state, { payload }) {
return { ...state, editingOrder: payload }
}
}
}
services层:(这里的接口是后端提供),需要设置跨域代理
import request from '@/utils/request';
import { stringify } from 'qs';
import _ from 'lodash';
import { urlencoded } from '@/utils/urlencoded';
// 未处理列表
export async function orderList() {
return request('/api/sms-1.0.0/user/list');
}
// 已处理
export async function pendedList() {
return request('/api/sms-1.0.0/user/pended');
}
// 添加订单
export async function orderAdd(values) {
return request(`/api/sms-1.0.0/user/add?${stringify(values)}`,{ method:'POST'});
}
// 删除订单
export async function orderDelete(uuid) {
return request(`/api/sms-1.0.0/user/delete?uuid=${uuid}`);
}
// 查询编辑的那条信息
export async function searchbyUUID(uuid) {
return request(`/api/sms-1.0.0/user/get_by_uuid?uuid=${uuid}`);
}
// 编辑订单
export async function orderEdit(values) {
console.warn('CCCCCCCCCCCCCCCCCCCCCCCCC',values);
return request(`/api/sms-1.0.0/user/edit?${stringify(values)}`,{ method: 'POST'});
}
// 标记已处理订单
export async function onMarkOrder(uuid) {
return request(`/api/sms-1.0.0/user/pending?uuid=${uuid}`);
}
// 查询
export async function queryByNameOrPhone(values) {
// if (!values) return;
if (values.phone === undefined && values.username !== undefined) {
return request(`/api/sms-1.0.0/user/username_search?username=${values.username}`);
}
// return request(`/api/sms-1.0.0/user/username_search?username=${values.username}`);
return request(`/api/sms-1.0.0/user/phone_search?phone=${values.phone}`);
}
request.js: 封装好的请求函数
/**
* request 网络请求工具
* 更详细的api文档: https://bigfish.alipay.com/doc/api#request
*/
import { extend } from 'umi-request';
import { notification } from 'antd';
import router from 'umi/router';
const codeMessage = {
200: '服务器成功返回请求的数据。',
201: '新建或修改数据成功。',
202: '一个请求已经进入后台排队(异步任务)。',
204: '删除数据成功。',
400: '发出的请求有错误,服务器没有进行新建或修改数据的操作。',
401: '用户没有权限(令牌、用户名、密码错误)。',
403: '用户得到授权,但是访问是被禁止的。',
404: '发出的请求针对的是不存在的记录,服务器没有进行操作。',
406: '请求的格式不可得。',
410: '请求的资源被永久删除,且不会再得到的。',
422: '当创建一个对象时,发生一个验证错误。',
500: '服务器发生错误,请检查服务器。',
502: '网关错误。',
503: '服务不可用,服务器暂时过载或维护。',
504: '网关超时。',
};
/**
* 异常处理程序
*/
const errorHandler = error => {
const { response = {} } = error;
const errortext = codeMessage[response.status] || response.statusText;
const { status, url } = response;
if (status === 401) {
notification.error({
message: '未登录或登录已过期,请重新登录。',
});
// @HACK
/* eslint-disable no-underscore-dangle */
window.g_app._store.dispatch({
type: 'login/logout',
});
return;
}
notification.error({
message: `请求错误 ${status}: ${url}`,
description: errortext,
});
// environment should not be used
if (status === 403) {
router.push('/exception/403');
return;
}
if (status <= 504 && status >= 500) {
router.push('/exception/500');
return;
}
if (status >= 404 && status < 422) {
router.push('/exception/404');
}
};
/**
* 配置request请求时的默认参数
*/
const request = extend({
errorHandler, // 默认错误处理
credentials: 'include', // 默认请求是否带上cookie
});
export default request;