diff --git a/admin-web/config/config.js b/admin-web/config/config.js
index 95c640a50..0e63fb05c 100644
--- a/admin-web/config/config.js
+++ b/admin-web/config/config.js
@@ -65,7 +65,7 @@ if (APP_TYPE === 'site') {
export default {
// add for transfer to umi
base: basePath,
- publicPath: basePath,
+ // publicPath: basePath,
plugins,
define: {
APP_TYPE: APP_TYPE || '',
diff --git a/admin-web/config/router.config.js b/admin-web/config/router.config.js
index 920467940..932f5bee0 100644
--- a/admin-web/config/router.config.js
+++ b/admin-web/config/router.config.js
@@ -69,6 +69,11 @@ export default [
name: 'order-list',
component: './Order/OrderList',
},
+ {
+ path: '/order/order-refunds',
+ name: 'order-refunds',
+ component: './Order/OrderRefunds',
+ },
],
},
// product
diff --git a/admin-web/src/components/OrderTable/index.js b/admin-web/src/components/OrderTable/index.js
new file mode 100644
index 000000000..2c74867eb
--- /dev/null
+++ b/admin-web/src/components/OrderTable/index.js
@@ -0,0 +1,8 @@
+// import React, { PureComponent } from 'react';
+// import {} from 'antd';
+//
+// export default class OrderTable extends PureComponent {
+// render() {
+// return
cc
;
+// }
+// }
diff --git a/admin-web/src/locales/zh-CN/menu.js b/admin-web/src/locales/zh-CN/menu.js
index 111932c6a..9695fe996 100644
--- a/admin-web/src/locales/zh-CN/menu.js
+++ b/admin-web/src/locales/zh-CN/menu.js
@@ -52,6 +52,7 @@ export default {
// 订单
'menu.order': '订单管理',
'menu.order.order-list': '订单管理',
+ 'menu.order.order-refunds': '退货维权',
// 营销相关
- 'menu.promotion.promotion-banner-list': 'Banner 管理'
+ 'menu.promotion.promotion-banner-list': 'Banner 管理',
};
diff --git a/admin-web/src/models/order/orderDelivery.js b/admin-web/src/models/order/orderDelivery.js
new file mode 100644
index 000000000..6aa33ebb4
--- /dev/null
+++ b/admin-web/src/models/order/orderDelivery.js
@@ -0,0 +1,25 @@
+// import { cancelOrder } from '../../services/order';
+//
+// export default {
+// namespace: 'orderDelivery',
+//
+// state: {
+// orderId: 0,
+// visible: false,
+// },
+//
+// effects: {
+// *getLogistics({ payload }, { call, put }) {},
+// },
+//
+// reducers: {
+// changeVisible(state, { payload }) {
+// const { orderId, visible } = payload;
+// return {
+// ...state,
+// orderId,
+// visible,
+// };
+// },
+// },
+// };
diff --git a/admin-web/src/models/order/orderList.js b/admin-web/src/models/order/orderList.js
index babef4370..4a3468e93 100644
--- a/admin-web/src/models/order/orderList.js
+++ b/admin-web/src/models/order/orderList.js
@@ -1,5 +1,11 @@
import { message } from 'antd';
-import { orderPage, updateOrderItem, updateOrderItemPayAmount } from '../../services/order';
+import {
+ orderPage,
+ updateOrderItem,
+ updateOrderItemPayAmount,
+ updateRemark,
+ cancelOrder,
+} from '../../services/order';
export default {
namespace: 'orderList',
@@ -18,6 +24,12 @@ export default {
orderId: 0,
orderItemId: 0,
searchParams: {},
+
+ remarkVisible: false,
+ remark: '',
+
+ orderCancelVisible: false,
+ orderCancelShowOther: false,
},
effects: {
@@ -70,6 +82,40 @@ export default {
},
});
+ yield put({
+ type: 'queryPage',
+ payload: {
+ ...searchParams,
+ },
+ });
+ },
+ *updateRemake({ payload }, { call, put }) {
+ const { searchParams, params } = payload;
+ yield call(updateRemark, params);
+ yield put({
+ type: 'changeRemakeVisible',
+ payload: {
+ remarkVisible: false,
+ },
+ });
+
+ yield put({
+ type: 'queryPage',
+ payload: {
+ ...searchParams,
+ },
+ });
+ },
+ *cancelOrder({ payload }, { call, put }) {
+ const { searchParams, params } = payload;
+ yield call(cancelOrder, params);
+ yield put({
+ type: 'changeOrderCancelVisible',
+ payload: {
+ orderCancelVisible: false,
+ },
+ });
+
yield put({
type: 'queryPage',
payload: {
@@ -99,5 +145,23 @@ export default {
...payload,
};
},
+ changeRemakeVisible(state, { payload }) {
+ return {
+ ...state,
+ ...payload,
+ };
+ },
+ changeOrderCancelVisible(state, { payload }) {
+ return {
+ ...state,
+ ...payload,
+ };
+ },
+ changeOrderCancelShowOther(state, { payload }) {
+ return {
+ ...state,
+ ...payload,
+ };
+ },
},
};
diff --git a/admin-web/src/pages/Order/OrderCancel.js b/admin-web/src/pages/Order/OrderCancel.js
new file mode 100644
index 000000000..5a58df109
--- /dev/null
+++ b/admin-web/src/pages/Order/OrderCancel.js
@@ -0,0 +1,84 @@
+import React from 'react';
+import { Form, Input, Modal } from 'antd';
+import DictionarySelect from '@/components/Dictionary/DictionarySelect';
+import dictionary from '@/utils/dictionary';
+
+const FormItem = Form.Item;
+
+// 订单 - 更新支付金额
+const OrderCancel = Form.create()(props => {
+ const { form, dispatch, loading } = props;
+ const { orderId, orderCancelVisible, orderCancelShowOther, searchParams } = props.orderList;
+ const { getFieldDecorator } = props.form;
+
+ const handleOk = e => {
+ e.preventDefault();
+ form.validateFields((err, fields) => {
+ if (err) return;
+ dispatch({
+ type: 'orderList/cancelOrder',
+ payload: {
+ params: {
+ orderId,
+ reasons: fields.reasons,
+ otherReasons: fields.otherReasons,
+ },
+ searchParams,
+ },
+ });
+ });
+ };
+
+ const handleCancel = () => {
+ dispatch({
+ type: 'orderList/changeRemakeVisible',
+ payload: {
+ remarkVisible: false,
+ },
+ });
+ };
+
+ const handleReasonsChange = key => {
+ dispatch({
+ type: 'orderList/changeOrderCancelShowOther',
+ payload: {
+ orderCancelShowOther: key === '20',
+ },
+ });
+ };
+
+ return (
+
+
+ {getFieldDecorator('reasons', {
+ rules: [{ required: true, message: '请选择取消原因!' }],
+ })(
+
+ )}
+
+ {orderCancelShowOther ? (
+
+ {getFieldDecorator('otherReasons', {
+ rules: [{ required: true, message: '请输填写退款原因!' }],
+ })()}
+
+ ) : (
+ ''
+ )}
+
+ );
+});
+
+export default OrderCancel;
diff --git a/admin-web/src/pages/Order/OrderDelivery.js b/admin-web/src/pages/Order/OrderDelivery.js
new file mode 100644
index 000000000..f03e59668
--- /dev/null
+++ b/admin-web/src/pages/Order/OrderDelivery.js
@@ -0,0 +1,5 @@
+// import React, { PureComponent } from 'react';
+//
+// class OrderDelivery extends PureComponent {}
+//
+// export default OrderDelivery;
diff --git a/admin-web/src/pages/Order/OrderDetails.js b/admin-web/src/pages/Order/OrderDetails.js
new file mode 100644
index 000000000..f1635f53a
--- /dev/null
+++ b/admin-web/src/pages/Order/OrderDetails.js
@@ -0,0 +1,691 @@
+import React, { PureComponent, Fragment } from 'react';
+import { connect } from 'dva';
+import moment from 'moment';
+import router from 'umi/router';
+import {
+ Row,
+ Col,
+ Card,
+ Form,
+ Input,
+ Select,
+ Icon,
+ Button,
+ Dropdown,
+ Menu,
+ InputNumber,
+ DatePicker,
+ Modal,
+ message,
+ Badge,
+ Divider,
+ Steps,
+ Radio,
+} from 'antd';
+import StandardTable from '@/components/StandardTable';
+import PageHeaderWrapper from '@/components/PageHeaderWrapper';
+
+import styles from './OrderDetails.less';
+
+const FormItem = Form.Item;
+const { Step } = Steps;
+const { TextArea } = Input;
+const { Option } = Select;
+const RadioGroup = Radio.Group;
+const getValue = obj =>
+ Object.keys(obj)
+ .map(key => obj[key])
+ .join(',');
+const statusMap = ['default', 'processing', 'success', 'error'];
+const status = ['关闭', '运行中', '已上线', '异常'];
+
+const CreateForm = Form.create()(props => {
+ const { modalVisible, form, handleAdd, handleModalVisible } = props;
+ const okHandle = () => {
+ form.validateFields((err, fieldsValue) => {
+ if (err) return;
+ form.resetFields();
+ handleAdd(fieldsValue);
+ });
+ };
+ return (
+ handleModalVisible()}
+ >
+
+ {form.getFieldDecorator('desc', {
+ rules: [{ required: true, message: '请输入至少五个字符的规则描述!', min: 5 }],
+ })()}
+
+
+ );
+});
+
+@Form.create()
+class UpdateForm extends PureComponent {
+ static defaultProps = {
+ handleUpdate: () => {},
+ handleUpdateModalVisible: () => {},
+ values: {},
+ };
+
+ constructor(props) {
+ super(props);
+
+ this.state = {
+ formVals: {
+ name: props.values.name,
+ desc: props.values.desc,
+ key: props.values.key,
+ target: '0',
+ template: '0',
+ type: '1',
+ time: '',
+ frequency: 'month',
+ },
+ currentStep: 0,
+ };
+
+ this.formLayout = {
+ labelCol: { span: 7 },
+ wrapperCol: { span: 13 },
+ };
+ }
+
+ handleNext = currentStep => {
+ const { form, handleUpdate } = this.props;
+ const { formVals: oldValue } = this.state;
+ form.validateFields((err, fieldsValue) => {
+ if (err) return;
+ const formVals = { ...oldValue, ...fieldsValue };
+ this.setState(
+ {
+ formVals,
+ },
+ () => {
+ if (currentStep < 2) {
+ this.forward();
+ } else {
+ handleUpdate(formVals);
+ }
+ }
+ );
+ });
+ };
+
+ backward = () => {
+ const { currentStep } = this.state;
+ this.setState({
+ currentStep: currentStep - 1,
+ });
+ };
+
+ forward = () => {
+ const { currentStep } = this.state;
+ this.setState({
+ currentStep: currentStep + 1,
+ });
+ };
+
+ renderContent = (currentStep, formVals) => {
+ const { form } = this.props;
+ if (currentStep === 1) {
+ return [
+
+ {form.getFieldDecorator('target', {
+ initialValue: formVals.target,
+ })(
+
+ )}
+ ,
+
+ {form.getFieldDecorator('template', {
+ initialValue: formVals.template,
+ })(
+
+ )}
+ ,
+
+ {form.getFieldDecorator('type', {
+ initialValue: formVals.type,
+ })(
+
+ 强
+ 弱
+
+ )}
+ ,
+ ];
+ }
+ if (currentStep === 2) {
+ return [
+
+ {form.getFieldDecorator('time', {
+ rules: [{ required: true, message: '请选择开始时间!' }],
+ })(
+
+ )}
+ ,
+
+ {form.getFieldDecorator('frequency', {
+ initialValue: formVals.frequency,
+ })(
+
+ )}
+ ,
+ ];
+ }
+ return [
+
+ {form.getFieldDecorator('name', {
+ rules: [{ required: true, message: '请输入规则名称!' }],
+ initialValue: formVals.name,
+ })()}
+ ,
+
+ {form.getFieldDecorator('desc', {
+ rules: [{ required: true, message: '请输入至少五个字符的规则描述!', min: 5 }],
+ initialValue: formVals.desc,
+ })()}
+ ,
+ ];
+ };
+
+ renderFooter = currentStep => {
+ const { handleUpdateModalVisible, values } = this.props;
+ if (currentStep === 1) {
+ return [
+ ,
+ ,
+ ,
+ ];
+ }
+ if (currentStep === 2) {
+ return [
+ ,
+ ,
+ ,
+ ];
+ }
+ return [
+ ,
+ ,
+ ];
+ };
+
+ render() {
+ const { updateModalVisible, handleUpdateModalVisible, values } = this.props;
+ const { currentStep, formVals } = this.state;
+
+ return (
+ handleUpdateModalVisible(false, values)}
+ afterClose={() => handleUpdateModalVisible()}
+ >
+
+
+
+
+
+ {this.renderContent(currentStep, formVals)}
+
+ );
+ }
+}
+
+/* eslint react/no-multi-comp:0 */
+@connect(({ rule, loading }) => ({
+ rule,
+ loading: loading.models.rule,
+}))
+@Form.create()
+class TableList extends PureComponent {
+ state = {
+ modalVisible: false,
+ updateModalVisible: false,
+ expandForm: false,
+ selectedRows: [],
+ formValues: {},
+ stepFormValues: {},
+ };
+
+ columns = [
+ {
+ title: '规则名称',
+ dataIndex: 'name',
+ render: text => this.previewItem(text)}>{text},
+ },
+ {
+ title: '描述',
+ dataIndex: 'desc',
+ },
+ {
+ title: '服务调用次数',
+ dataIndex: 'callNo',
+ sorter: true,
+ render: val => `${val} 万`,
+ // mark to display a total number
+ needTotal: true,
+ },
+ {
+ title: '状态',
+ dataIndex: 'status',
+ filters: [
+ {
+ text: status[0],
+ value: 0,
+ },
+ {
+ text: status[1],
+ value: 1,
+ },
+ {
+ text: status[2],
+ value: 2,
+ },
+ {
+ text: status[3],
+ value: 3,
+ },
+ ],
+ render(val) {
+ return ;
+ },
+ },
+ {
+ title: '上次调度时间',
+ dataIndex: 'updatedAt',
+ sorter: true,
+ render: val => {moment(val).format('YYYY-MM-DD HH:mm:ss')},
+ },
+ {
+ title: '操作',
+ render: (text, record) => (
+
+ this.handleUpdateModalVisible(true, record)}>配置
+
+ 订阅警报
+
+ ),
+ },
+ ];
+
+ componentDidMount() {
+ const { dispatch } = this.props;
+ dispatch({
+ type: 'rule/fetch',
+ });
+ }
+
+ handleStandardTableChange = (pagination, filtersArg, sorter) => {
+ const { dispatch } = this.props;
+ const { formValues } = this.state;
+
+ const filters = Object.keys(filtersArg).reduce((obj, key) => {
+ const newObj = { ...obj };
+ newObj[key] = getValue(filtersArg[key]);
+ return newObj;
+ }, {});
+
+ const params = {
+ currentPage: pagination.current,
+ pageSize: pagination.pageSize,
+ ...formValues,
+ ...filters,
+ };
+ if (sorter.field) {
+ params.sorter = `${sorter.field}_${sorter.order}`;
+ }
+
+ dispatch({
+ type: 'rule/fetch',
+ payload: params,
+ });
+ };
+
+ previewItem = id => {
+ router.push(`/profile/basic/${id}`);
+ };
+
+ handleFormReset = () => {
+ const { form, dispatch } = this.props;
+ form.resetFields();
+ this.setState({
+ formValues: {},
+ });
+ dispatch({
+ type: 'rule/fetch',
+ payload: {},
+ });
+ };
+
+ toggleForm = () => {
+ const { expandForm } = this.state;
+ this.setState({
+ expandForm: !expandForm,
+ });
+ };
+
+ handleMenuClick = e => {
+ const { dispatch } = this.props;
+ const { selectedRows } = this.state;
+
+ if (selectedRows.length === 0) return;
+ switch (e.key) {
+ case 'remove':
+ dispatch({
+ type: 'rule/remove',
+ payload: {
+ key: selectedRows.map(row => row.key),
+ },
+ callback: () => {
+ this.setState({
+ selectedRows: [],
+ });
+ },
+ });
+ break;
+ default:
+ break;
+ }
+ };
+
+ handleSelectRows = rows => {
+ this.setState({
+ selectedRows: rows,
+ });
+ };
+
+ handleSearch = e => {
+ e.preventDefault();
+
+ const { dispatch, form } = this.props;
+
+ form.validateFields((err, fieldsValue) => {
+ if (err) return;
+
+ const values = {
+ ...fieldsValue,
+ updatedAt: fieldsValue.updatedAt && fieldsValue.updatedAt.valueOf(),
+ };
+
+ this.setState({
+ formValues: values,
+ });
+
+ dispatch({
+ type: 'rule/fetch',
+ payload: values,
+ });
+ });
+ };
+
+ handleModalVisible = flag => {
+ this.setState({
+ modalVisible: !!flag,
+ });
+ };
+
+ handleUpdateModalVisible = (flag, record) => {
+ this.setState({
+ updateModalVisible: !!flag,
+ stepFormValues: record || {},
+ });
+ };
+
+ handleAdd = fields => {
+ const { dispatch } = this.props;
+ dispatch({
+ type: 'rule/add',
+ payload: {
+ desc: fields.desc,
+ },
+ });
+
+ message.success('添加成功');
+ this.handleModalVisible();
+ };
+
+ handleUpdate = fields => {
+ const { dispatch } = this.props;
+ const { formValues } = this.state;
+ dispatch({
+ type: 'rule/update',
+ payload: {
+ query: formValues,
+ body: {
+ name: fields.name,
+ desc: fields.desc,
+ key: fields.key,
+ },
+ },
+ });
+
+ message.success('配置成功');
+ this.handleUpdateModalVisible();
+ };
+
+ renderSimpleForm() {
+ const {
+ form: { getFieldDecorator },
+ } = this.props;
+ return (
+
+ );
+ }
+
+ renderAdvancedForm() {
+ const {
+ form: { getFieldDecorator },
+ } = this.props;
+ return (
+
+ );
+ }
+
+ renderForm() {
+ const { expandForm } = this.state;
+ return expandForm ? this.renderAdvancedForm() : this.renderSimpleForm();
+ }
+
+ render() {
+ const {
+ rule: { data },
+ loading,
+ } = this.props;
+ const { selectedRows, modalVisible, updateModalVisible, stepFormValues } = this.state;
+ const menu = (
+
+ );
+
+ const parentMethods = {
+ handleAdd: this.handleAdd,
+ handleModalVisible: this.handleModalVisible,
+ };
+ const updateMethods = {
+ handleUpdateModalVisible: this.handleUpdateModalVisible,
+ handleUpdate: this.handleUpdate,
+ };
+ return (
+
+
+
+
{this.renderForm()}
+
+
+ {selectedRows.length > 0 && (
+
+
+
+
+
+
+ )}
+
+
+
+
+
+ {stepFormValues && Object.keys(stepFormValues).length ? (
+
+ ) : null}
+
+ );
+ }
+}
+
+export default TableList;
diff --git a/admin-web/src/pages/Order/OrderDetails.less b/admin-web/src/pages/Order/OrderDetails.less
new file mode 100644
index 000000000..bc5601c1a
--- /dev/null
+++ b/admin-web/src/pages/Order/OrderDetails.less
@@ -0,0 +1,49 @@
+@import '~antd/lib/style/themes/default.less';
+@import '~@/utils/utils.less';
+
+.tableList {
+ .tableListOperator {
+ margin-bottom: 16px;
+ button {
+ margin-right: 8px;
+ }
+ }
+}
+
+.tableListForm {
+ :global {
+ .ant-form-item {
+ display: flex;
+ margin-right: 0;
+ margin-bottom: 24px;
+ > .ant-form-item-label {
+ width: auto;
+ padding-right: 8px;
+ line-height: 32px;
+ }
+ .ant-form-item-control {
+ line-height: 32px;
+ }
+ }
+ .ant-form-item-control-wrapper {
+ flex: 1;
+ }
+ }
+ .submitButtons {
+ display: block;
+ margin-bottom: 24px;
+ white-space: nowrap;
+ }
+}
+
+@media screen and (max-width: @screen-lg) {
+ .tableListForm :global(.ant-form-item) {
+ margin-right: 24px;
+ }
+}
+
+@media screen and (max-width: @screen-md) {
+ .tableListForm :global(.ant-form-item) {
+ margin-right: 8px;
+ }
+}
diff --git a/admin-web/src/pages/Order/OrderList.js b/admin-web/src/pages/Order/OrderList.js
index 6111fc59d..d4ba0f8e4 100644
--- a/admin-web/src/pages/Order/OrderList.js
+++ b/admin-web/src/pages/Order/OrderList.js
@@ -6,6 +6,8 @@ import { Button, Card, Col, Divider, Form, Input, Row, Tabs, DatePicker, List }
import PageHeaderWrapper from '@/components/PageHeaderWrapper';
import DictionaryText from '@/components/Dictionary/DictionaryText';
import OrderUpdatePayAmount from './OrderUpdatePayAmount';
+import OrderRemark from './OrderRemark';
+import OrderCancel from './OrderCancel';
import dictionary from '@/utils/dictionary';
import styles from './OrderList.less';
@@ -14,8 +16,10 @@ const { RangePicker } = DatePicker;
const FormItem = Form.Item;
const { TabPane } = Tabs;
-const OrderContent = orderItem => {
- const { dispatch, skuName, skuImage, quantity, price, payAmount, createTime, status } = orderItem;
+const OrderContent = props => {
+ const { dispatch, item } = props;
+ const { createTime, status, payAmount } = item;
+ const { name, mobile } = item.orderRecipient;
const handleUpdatePayAmount = updateOrderItem => {
dispatch({
@@ -29,27 +33,58 @@ const OrderContent = orderItem => {
});
};
+ // const handleCancelOrder = ({ orderId }) => {
+ // dispatch({
+ // type: 'orderList/changeOrderCancelVisible',
+ // payload: {
+ // orderCancelVisible: true,
+ // orderId,
+ // },
+ // });
+ // };
+ //
+ // const handleRenderGoods = () => {};
+
+ const renderStatusButtons = () => {
+ let res = '';
+ if (status === 1) {
+ res = ;
+ } else if (status === 2) {
+ res = ;
+ }
+ return res;
+ };
+
+ const renderGoods = orderItems => {
+ return orderItems.map(({ skuName, skuImage, quantity, price }) => {
+ return (
+
+
+
+
+
{quantity}件
+
+ {price / 100} 元/{quantity * (price / 100)} 元
+
+
+
+ );
+ });
+ };
+
return (
-
-
-
(名称)
-
-
秋季精选
+
+ {renderGoods(item.orderItems)}
-
(金额/物件)
-
{quantity}件
-
- {price / 100} 元/{quantity * (price / 100)} 元
-
-
-
-
(购买人)
-
范先生
-
13302926050
+
{name}
+
{mobile}
(下单时间)
@@ -57,17 +92,16 @@ const OrderContent = orderItem => {
-
(订单状态)
-
{[0, 1, 2].indexOf(status) ? : ''}
+
{renderStatusButtons()}
(实付金额)
{payAmount / 100}元
@@ -82,6 +116,18 @@ const OrderList = props => {
...pagination,
};
+ const handleRemakeClick = item => {
+ const { id, remark } = item;
+ dispatch({
+ type: 'orderList/changeRemakeVisible',
+ payload: {
+ remarkVisible: true,
+ orderId: id,
+ remark,
+ },
+ });
+ };
+
return (
{
- {item.orderItems.map(orderItem => {
- return ;
- })}
+
)}
@@ -131,11 +175,9 @@ const SearchForm = Form.create()(props => {
form.validateFields((err, fields) => {
const buildTime = (fieldValue, key) => {
const res = {};
- if (fieldValue) {
+ if (fieldValue && fieldValue.length >= 2) {
const keySuffix = key.substring(0, 1).toUpperCase() + key.substring(1);
- // res[`start${keySuffix}`] = fieldValue[0].valueOf();
res[`start${keySuffix}`] = fieldValue[0].format('YYYY-MM-DD HH:mm:ss');
- // res[`end${keySuffix}`] = fieldValue[1].valueOf();
res[`end${keySuffix}`] = fieldValue[1].format('YYYY-MM-DD HH:mm:ss');
}
return res;
@@ -186,9 +228,6 @@ const SearchForm = Form.create()(props => {
{getFieldDecorator('createTime')()}
-
- {getFieldDecorator('closingTime')()}
-