Commit cd6b961e authored by 李腾's avatar 李腾

feat: 完善售后取消订单逻辑

parent 7534953c
import React from 'react'; import React, { useState } from 'react';
import { Form, Input, Select, DatePicker, Button, Space } from 'antd'; import { Form, Input, Select, DatePicker, Button, Space } from 'antd';
import { moment, Moment } from 'moment'; import moment from 'moment';
import style from './index.less'; import style from './index.less';
const { Option } = Select; const { Option } = Select;
...@@ -82,11 +82,27 @@ const FormSearch = props => { ...@@ -82,11 +82,27 @@ const FormSearch = props => {
// 选择日期范围类型 // 选择日期范围类型
const FormItemRangePicker = config => { const FormItemRangePicker = config => {
const { originOptions = {} } = config; const { originOptions = {}, bindKey, rangeNum, rangeUnit } = config;
const attrs = { placeholder: ['开始日期', '结束日期'], ...originOptions }; const attrs = { placeholder: ['开始日期', '结束日期'], ...originOptions };
// 自动截取日期限制的范围
const onOpenChange = open => {
if (!open) {
const [date1, date2] = form.getFieldValue(bindKey);
const diffNum = date2.diff(date1, 'months');
if (diffNum >= 3) {
setTimeout(() => {
form.setFieldsValue({
[bindKey]: [moment(date1), moment(date1).add(3, 'month')],
});
});
}
}
};
return ( return (
<FormItemBox {...config}> <FormItemBox {...config}>
<RangePicker className={style['form-item-tag']} {...attrs} /> <RangePicker className={style['form-item-tag']} onOpenChange={onOpenChange} {...attrs} />
</FormItemBox> </FormItemBox>
); );
}; };
...@@ -107,7 +123,7 @@ const FormSearch = props => { ...@@ -107,7 +123,7 @@ const FormSearch = props => {
// 输入框类型 // 输入框类型
const FormItemInput = config => { const FormItemInput = config => {
const { originOptions = {} } = config; const { originOptions = {} } = config;
const attrs = { placeholder: '请输入', ...originOptions }; const attrs = { placeholder: '请输入', allowClear: true, ...originOptions };
return ( return (
<FormItemBox {...config}> <FormItemBox {...config}>
<Input className={style['form-item-tag']} {...attrs} /> <Input className={style['form-item-tag']} {...attrs} />
......
import React, { useState, useEffect, forwardRef, useImperativeHandle } from 'react'; import React, { useState, useEffect, forwardRef, useImperativeHandle } from 'react';
import { useHistory } from 'react-router-dom';
import { Modal, Tabs, Pagination, Spin, notification, Checkbox, Badge } from 'antd'; import { Modal, Tabs, Pagination, Spin, notification, Checkbox, Badge } from 'antd';
import { apiGetBussinessMsgList, apiGetBusinessMsgUnReadCount } from '@/services/messageReminder'; import { apiGetBussinessMsgList, apiGetBusinessMsgUnReadCount } from '@/services/messageReminder';
import { connect } from 'dva'; import { connect } from 'dva';
...@@ -16,7 +17,7 @@ const INIT_QUERY_PARAMS = { ...@@ -16,7 +17,7 @@ const INIT_QUERY_PARAMS = {
}; };
const MessageItem = props => { const MessageItem = props => {
const { item, onMark } = props; const { item, onMark, viewDetail } = props;
/** /**
* type: 0订单消息,1售后消息 * type: 0订单消息,1售后消息
* readStatus: 0未读,1已读 * readStatus: 0未读,1已读
...@@ -28,11 +29,18 @@ const MessageItem = props => { ...@@ -28,11 +29,18 @@ const MessageItem = props => {
} catch (e) { } catch (e) {
console.error('消息数据格式错误'); console.error('消息数据格式错误');
} }
const goodList = message.items.map(good => (
<div className={styles.good}>
<span className={styles.good__name}>{good.skuName}</span>
<span className={styles.good__count}>x{good.quantity}</span>
</div>
));
return ( return (
<div className={styles['complex-list__item']}> <div className={styles['complex-list__item']}>
<div className={styles['complex-list__item--header']}> <div className={styles['complex-list__item--header']}>
<span className={styles['order-number']}> 订单编号:{message.orderNo}</span> <span className={styles['order-number']}> 订单编号:{message.orderNo}</span>
<span className={styles.time}>订单时间:{message.createdAt}</span> <span className={styles.time}>订单时间:{message.time}</span>
{readStatus === 0 ? ( {readStatus === 0 ? (
<a className={styles['read-status']} onClick={() => onMark([item.id])}> <a className={styles['read-status']} onClick={() => onMark([item.id])}>
标记为已读 标记为已读
...@@ -41,15 +49,12 @@ const MessageItem = props => { ...@@ -41,15 +49,12 @@ const MessageItem = props => {
<span className={styles['read-status--read']}>已读</span> <span className={styles['read-status--read']}>已读</span>
)} )}
</div> </div>
<div className={styles['complex-list__item--body']}> <div className={styles['complex-list__item--body']}>{goodList}</div>
<div className={styles.good}>
<span className={styles.good__name}>商品名称商品名称商品名称商品名称</span>
<span className={styles.good__count}>x10</span>
</div>
</div>
<div className={styles['complex-list__item--footer']}> <div className={styles['complex-list__item--footer']}>
<div className={styles.actions}> <div className={styles.actions}>
<a className={styles.notice}>新的xxx订单,请查看</a> <a onClick={() => viewDetail(message)} className={styles.notice}>
{message.title},请查看
</a>
</div> </div>
</div> </div>
</div> </div>
...@@ -58,6 +63,7 @@ const MessageItem = props => { ...@@ -58,6 +63,7 @@ const MessageItem = props => {
const Complex = props => { const Complex = props => {
const { dispatch, refInstance } = props; const { dispatch, refInstance } = props;
const history = useHistory();
const [visible, setVisible] = useState(false); const [visible, setVisible] = useState(false);
const [dataTotal, setDataTotal] = useState(10); const [dataTotal, setDataTotal] = useState(10);
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
...@@ -133,6 +139,33 @@ const Complex = props => { ...@@ -133,6 +139,33 @@ const Complex = props => {
}); });
}; };
const open = () => {
setVisible(true);
getMsgReadCount();
};
const close = () => {
setVisible(false);
};
// 跳转到详情
const viewDetail = message => {
console.log(message);
const { orderNo } = message;
// 待发货
history.push({
pathname: '/orderManage/pendingDeliveryOrder',
query: { orderNo },
});
// 已发货
// /orderManage/deliveryOrder
// 售后
close();
};
// 切换消息类型 // 切换消息类型
const onTabChange = index => { const onTabChange = index => {
setQueryParams({ setQueryParams({
...@@ -161,15 +194,6 @@ const Complex = props => { ...@@ -161,15 +194,6 @@ const Complex = props => {
}); });
}; };
const open = () => {
setVisible(true);
getMsgReadCount();
};
const close = () => {
setVisible(false);
};
// 展开初始化 // 展开初始化
useEffect(() => { useEffect(() => {
if (visible) { if (visible) {
...@@ -261,7 +285,9 @@ const Complex = props => { ...@@ -261,7 +285,9 @@ const Complex = props => {
<FilterRender /> <FilterRender />
<div className={styles['complex-list']}> <div className={styles['complex-list']}>
{messageData.length ? ( {messageData.length ? (
messageData.map(item => <MessageItem key={item.id} item={item} onMark={onMark} />) messageData.map(item => (
<MessageItem key={item.id} item={item} onMark={onMark} viewDetail={viewDetail} />
))
) : ( ) : (
<Empty text="暂无数据" /> <Empty text="暂无数据" />
)} )}
......
...@@ -31,6 +31,7 @@ const Message = props => { ...@@ -31,6 +31,7 @@ const Message = props => {
} catch (e) { } catch (e) {
console.error('消息数据格式错误'); console.error('消息数据格式错误');
} }
return ( return (
<div className={styles.item}> <div className={styles.item}>
<div className={styles.info}> <div className={styles.info}>
...@@ -43,7 +44,7 @@ const Message = props => { ...@@ -43,7 +44,7 @@ const Message = props => {
<span>{message.createdAt}</span> <span>{message.createdAt}</span>
</div> </div>
<div className={styles.notice}> <div className={styles.notice}>
<a>您有新的xxxxx订单,请查看</a> <a>{message.title},请查看</a>
</div> </div>
</div> </div>
); );
...@@ -125,7 +126,6 @@ const Simple = props => { ...@@ -125,7 +126,6 @@ const Simple = props => {
notification.error(res.msg); notification.error(res.msg);
return; return;
} }
console.log(res);
const { content } = res.data; const { content } = res.data;
setVisible(!!content.length); setVisible(!!content.length);
dispatch({ dispatch({
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
position: fixed; position: fixed;
right: 30px; right: 30px;
bottom: 10px; bottom: 10px;
z-index: 19;
// width: 112px; // width: 112px;
// height: 50px; // height: 50px;
color: #fff; color: #fff;
......
...@@ -53,11 +53,8 @@ const BasicLayout = props => { ...@@ -53,11 +53,8 @@ const BasicLayout = props => {
const [siderCollapsed, setSiderCollapsed] = useState(false); const [siderCollapsed, setSiderCollapsed] = useState(false);
const messageReminderComplexRef = useRef(); const messageReminderComplexRef = useRef();
/** // const audioRef = useRef()
* constructor
*/
useEffect(() => {
const token = window.localStorage.getItem('token'); const token = window.localStorage.getItem('token');
const channelId = 100001; const channelId = 100001;
const socket = new Socket({ const socket = new Socket({
...@@ -69,12 +66,15 @@ const BasicLayout = props => { ...@@ -69,12 +66,15 @@ const BasicLayout = props => {
console.log('连接成功3'); console.log('连接成功3');
}); });
useEffect(() => {
socket.event.on('message', msg => { socket.event.on('message', msg => {
console.log(msg); // audioRef.current.click()
dispatch({ dispatch({
type: 'messageReminder/setUnReadData', type: 'messageReminder/setUnReadData',
payload: [JSON.parse(msg.data)], payload: [JSON.parse(msg.data)],
}); });
// socket.play()
}); });
// let a = 100000000000; // let a = 100000000000;
// setInterval(() => { // setInterval(() => {
...@@ -85,7 +85,7 @@ const BasicLayout = props => { ...@@ -85,7 +85,7 @@ const BasicLayout = props => {
// channelId: 100001, // channelId: 100001,
// bussinessId: 'self_40', // bussinessId: 'self_40',
// type: 0, // type: 0,
// sendContent: `{"name":"商品21111", "orderNo":${a},"createdAt":"2022-10-13 12:12:12", "count":11}`, // sendContent: `{"name":"商品21111","title":"商品21111", "orderNo":${a},"createdAt":"2022-10-13 12:12:12", "count":11}`,
// readStatus: 0, // readStatus: 0,
// createdAt: '2022-10-18 14:05:12', // createdAt: '2022-10-18 14:05:12',
// updatedAt: '2022-10-18 17:15:19', // updatedAt: '2022-10-18 17:15:19',
...@@ -226,7 +226,7 @@ const BasicLayout = props => { ...@@ -226,7 +226,7 @@ const BasicLayout = props => {
<MessageReminder.Simple complexRef={messageReminderComplexRef} /> <MessageReminder.Simple complexRef={messageReminderComplexRef} />
<MessageReminder.Complex ref={messageReminderComplexRef} /> <MessageReminder.Complex ref={messageReminderComplexRef} />
{/* <audio id="myaudio" src="https://img.lkbang.net/10544.b57be67d.mp3" loop="loop" preload="preload" muted="muted" /> */} {/* <Button ref={audioRef} onClick={() => { socket.play() }}>声音</Button> */}
</ProLayout> </ProLayout>
); );
}; };
......
import React from 'react';
import { Form } from '@ant-design/compatible';
import '@ant-design/compatible/assets/index.css';
import { Modal, Input, Cascader, notification } from 'antd';
import { cancelShopAudit } from '../services';
const FormItem = Form.Item;
const { TextArea } = Input;
const AuditModal = props => {
const {
visible,
onCancel,
form: { getFieldDecorator, getFieldValue, validateFields, resetFields },
formData = {},
} = props;
const handleCancel = isSuccess => {
resetFields();
onCancel(isSuccess);
};
const treeData = [
{
label: '同意',
value: true,
},
{
label: '不同意',
value: false,
children: [
{
label: '订单已发货',
value: 10,
},
{
label: '已与客户沟通继续发货',
value: 20,
},
{
label: '其他',
value: 30,
},
],
},
];
const handleOk = () => {
validateFields(async (error, fieldsValue) => {
if (!error) {
const { approve } = fieldsValue;
const data = await cancelShopAudit({
...fieldsValue,
refuseReasonCode: approve?.[1],
approve: approve?.[0],
serviceNo: formData?.serviceNo,
});
if (data.businessCode === '0000') {
notification.success({ message: approve?.[0] ? '审核成功' : '审核拒绝提交成功' });
handleCancel(true);
}
}
});
};
const layout = {
labelCol: { span: 6 },
wrapperCol: { span: 16 },
};
const approve = getFieldValue('approve');
const isRefuse = () => approve && approve[0] !== 1;
return (
<Modal
title="售后操作确认"
visible={visible}
onOk={() => handleOk()}
onCancel={() => handleCancel()}
>
<Form {...layout} name="formData">
<FormItem label="审核结果">
{getFieldDecorator('approve')(
<Cascader
allowClear
showSearch
style={{ width: '315px' }}
dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
options={treeData}
placeholder="请选择"
/>,
)}
</FormItem>
{isRefuse() && approve[1] === 30 && (
<FormItem label="拒绝原因">
{getFieldDecorator('refuseReasonRemark', {
initialValue: formData.refuseDesc,
rules: [
{
required: true,
message: '请填写拒绝原因!',
},
],
})(
<TextArea
placeholder="请填写拒绝原因"
allowClear
autoSize={{ minRows: 3, maxRows: 6 }}
/>,
)}
</FormItem>
)}
</Form>
</Modal>
);
};
export default Form.create()(AuditModal);
import React from 'react';
import { Modal, Table } from 'antd';
export default props => {
const { visible, onCancel, dataSource } = props;
const handleCancel = () => {
onCancel();
};
const columns = [
{
title: '商品名称',
width: 400,
dataIndex: 'skuName',
},
{
title: '商品属性',
dataIndex: 'skuAttr',
},
{
title: '商品件数',
dataIndex: 'count',
},
];
return (
<Modal title="订单详情" visible={visible} onCancel={handleCancel} footer={null} width={800}>
<Table
dataSource={dataSource}
columns={columns}
key={r => r.orderId}
pagination={false}
bordered
/>
</Modal>
);
};
import React from 'react';
import { Form } from '@ant-design/compatible';
import '@ant-design/compatible/assets/index.css';
import { Modal, Input, notification } from 'antd';
import { shopCheck } from '../service';
const FormItem = Form.Item;
const { TextArea } = Input;
const RejectModal = props => {
const {
visible,
onCancel,
form: { getFieldDecorator, validateFields, resetFields },
serviceNo = null,
} = props;
const handleCancel = isSuccess => {
resetFields();
onCancel(isSuccess);
};
const handleOk = () => {
validateFields(async (error, fieldsValue) => {
if (!error) {
const data = await shopCheck({
...fieldsValue,
serviceNo,
auditResult: 2,
});
if (data.code === '0000') {
notification.success({ message: '操作成功' });
handleCancel(true);
}
}
});
};
const layout = {
labelCol: { span: 6 },
wrapperCol: { span: 16 },
};
return (
<Modal title="驳回" visible={visible} onOk={() => handleOk()} onCancel={() => handleCancel()}>
<Form {...layout} name="formData">
<FormItem label="原因">
{getFieldDecorator('refuseReasonRemark', {
rules: [
{
required: true,
message: '请填写原因!',
},
],
})(
<TextArea placeholder="请填写原因" allowClear autoSize={{ minRows: 3, maxRows: 6 }} />,
)}
</FormItem>
</Form>
</Modal>
);
};
export default Form.create()(RejectModal);
...@@ -130,16 +130,14 @@ export const getFormConfig = (props = {}) => { ...@@ -130,16 +130,14 @@ export const getFormConfig = (props = {}) => {
bindKey: 'receiverPhone', bindKey: 'receiverPhone',
}, },
{ {
type: SEARCH_TYPE.DATE_PICKER, type: SEARCH_TYPE.RANGE_PICKER,
label: '订单开始日期', label: '售后日期',
column: 5, column: 5,
bindKey: 'startDate', bindKey: 'afterTime',
originOptions: {
placeholder: ['开始日期', '结束日期'],
allowClear: false,
}, },
{
type: SEARCH_TYPE.DATE_PICKER,
label: '订单结束日期',
column: 5,
bindKey: 'endDate',
}, },
], ],
btnConfig: [ btnConfig: [
...@@ -152,9 +150,10 @@ export const getFormConfig = (props = {}) => { ...@@ -152,9 +150,10 @@ export const getFormConfig = (props = {}) => {
actionRef.current.reload(); actionRef.current.reload();
return; return;
} }
setTableParams(params);
const { type, dealStatus } = params; const { type, dealStatus } = params;
let hasMatchingKey = ''; let hasMatchingKey = '';
console.log(111111, params);
Object.keys(TAB_MAPPING_DATA).forEach(key => { Object.keys(TAB_MAPPING_DATA).forEach(key => {
const item = TAB_MAPPING_DATA[key]; const item = TAB_MAPPING_DATA[key];
if (type === item.type && dealStatus === item.dealStatus) { if (type === item.type && dealStatus === item.dealStatus) {
...@@ -162,14 +161,17 @@ export const getFormConfig = (props = {}) => { ...@@ -162,14 +161,17 @@ export const getFormConfig = (props = {}) => {
} }
}); });
setCurrentTab(hasMatchingKey); setCurrentTab(hasMatchingKey);
setTableParams(params);
}, },
}, },
{ {
label: '重置', label: '重置',
type: '', type: '',
clickType: 'reset', clickType: 'reset',
onClick: () => { onClick: ({ params }) => {
setTableParams({}); // setTableParams({});
actionRef.current.reload();
setCurrentTab('');
}, },
}, },
], ],
...@@ -193,6 +195,8 @@ export const getColumns = props => { ...@@ -193,6 +195,8 @@ export const getColumns = props => {
refund, refund,
reject, reject,
canEditable, canEditable,
openCancelAudit,
viewCancelDetail,
} = props; } = props;
return [ return [
{ {
...@@ -222,10 +226,18 @@ export const getColumns = props => { ...@@ -222,10 +226,18 @@ export const getColumns = props => {
title: '售后类型', title: '售后类型',
dataIndex: 'serviceType', dataIndex: 'serviceType',
hideInSearch: true, hideInSearch: true,
width: 120, width: 140,
render: serviceType => { render: serviceType => {
if (+serviceType === 0) {
return <span style={{ color: '#ff1616' }}>仅退款(未发货)</span>;
}
if (+serviceType === 1) { if (+serviceType === 1) {
return <span style={{ color: '#ff1616' }}>仅退款</span>; return (
<span style={{ color: '#ff1616' }}>
{/* {AFTER_TYPE.find(item=> item.value === serviceType)} */}
仅退款
</span>
);
} }
return <span>退货退款</span>; return <span>退货退款</span>;
}, },
...@@ -386,10 +398,11 @@ export const getColumns = props => { ...@@ -386,10 +398,11 @@ export const getColumns = props => {
key: 'pop', key: 'pop',
}; };
/** @name applyTpye=1 */
// 允许退款/已退款按钮 // 允许退款/已退款按钮
const refundBtn = ( const refundBtn = (
<Popconfirm {...refundBtnProps} onConfirm={() => refund(record)} disabled={!showRefund}> <Popconfirm {...refundBtnProps} onConfirm={() => refund(record)} disabled={!showRefund}>
<Button key="link1" disabled={!showRefund}> <Button key="link1" {...btnProps} disabled={!showRefund}>
{showRefunded ? '已退款' : '允许退款'} {showRefunded ? '已退款' : '允许退款'}
</Button> </Button>
</Popconfirm> </Popconfirm>
...@@ -400,6 +413,7 @@ export const getColumns = props => { ...@@ -400,6 +413,7 @@ export const getColumns = props => {
审核 审核
</Button> </Button>
); );
// 驳回按钮 // 驳回按钮
let refuseBtn = ( let refuseBtn = (
<Button key="link3" onClick={() => reject(record)} {...btnProps} disabled={!showRefuse}> <Button key="link3" onClick={() => reject(record)} {...btnProps} disabled={!showRefuse}>
...@@ -445,14 +459,28 @@ export const getColumns = props => { ...@@ -445,14 +459,28 @@ export const getColumns = props => {
</Button> </Button>
); );
const cancelAuditBtn = (
<Button key="cancellink1" onClick={() => openCancelAudit(record)} {...btnProps}>
审核
</Button>
);
const cancelDetailBtn = (
<Button key="cancellink2" onClick={() => viewCancelDetail(record)} {...btnProps}>
订单详情
</Button>
);
/** @name applyTpye=2 */
if (!canEditable) { if (!canEditable) {
auditBtn = ''; auditBtn = '';
refuseBtn = ''; refuseBtn = '';
logisticsInterceptionBtn = ''; logisticsInterceptionBtn = '';
} }
// 服务商品 || 实物商品-仅退款未发货 serviceType = 0 // 服务商品
if (isServiceGoods || serviceType === 0) { if (isServiceGoods) {
// 待商户审核14 // 待商户审核14
if ([14].includes(status)) { if ([14].includes(status)) {
return [auditBtn, detailBtn, viewLogBtn]; return [auditBtn, detailBtn, viewLogBtn];
...@@ -464,6 +492,19 @@ export const getColumns = props => { ...@@ -464,6 +492,19 @@ export const getColumns = props => {
} }
} }
// 实物商品-仅退款未发货 serviceType = 0
if (serviceType === 0) {
// 待商户审核14 待审核0
if ([14, 0].includes(status)) {
return [cancelAuditBtn, cancelDetailBtn, viewLogBtn];
}
// 拒绝16, 处理成功70
if ([16, 70].includes(status)) {
return [cancelDetailBtn, viewLogBtn];
}
}
// 实物商品-仅退款 serviceType = 1 // 实物商品-仅退款 serviceType = 1
if (serviceType === 1) { if (serviceType === 1) {
// 待商户审核14 // 待商户审核14
......
...@@ -13,6 +13,8 @@ import AppealDetail from '@/pages/afterSale/components/detail'; ...@@ -13,6 +13,8 @@ import AppealDetail from '@/pages/afterSale/components/detail';
import AfterLog from './components/AfterLog'; import AfterLog from './components/AfterLog';
import RejectModal from './components/rejectModal'; import RejectModal from './components/rejectModal';
import LogisticsCom from '../orderManage/pendingDeliveryOrder/components/LogisticsCom'; import LogisticsCom from '../orderManage/pendingDeliveryOrder/components/LogisticsCom';
import CancelAuditModal from './components/CancelAuditModal';
import CancelDetailTable from './components/CancelDetailTable';
import { getColumns, getFormConfig, TAB_MAPPING_DATA } from './data.js'; import { getColumns, getFormConfig, TAB_MAPPING_DATA } from './data.js';
import { getDetail } from '@/pages/afterSale/appeal/services'; import { getDetail } from '@/pages/afterSale/appeal/services';
...@@ -25,6 +27,7 @@ import { ...@@ -25,6 +27,7 @@ import {
trackInfo, trackInfo,
shopCheck, shopCheck,
getAfterPendingNum, getAfterPendingNum,
cancelOrderDetail,
} from './services'; } from './services';
import styles from './index.less'; import styles from './index.less';
...@@ -41,7 +44,13 @@ const AfterSale = props => { ...@@ -41,7 +44,13 @@ const AfterSale = props => {
const [currentTab, setCurrentTab] = useState(''); const [currentTab, setCurrentTab] = useState('');
const [appealDetailModal, setAppealDetailModal] = useState(false); const [appealDetailModal, setAppealDetailModal] = useState(false);
const [selectedRow, setSelectedRow] = useState({}); const [selectedRow, setSelectedRow] = useState({});
const [tabInfoData, setTabInfoData] = useState({}); const [tabInfoData, setTabInfoData] = useState({
cancelOrderPendingAuditNum: 0,
refundPendingAuditNum: 0,
returnPendingAuditNum: 0,
returnWaitAuditNum: 0,
afterSalseDoneNum: 0,
});
// 申诉 // 申诉
const [proofsData, setProofsData] = useState([]); const [proofsData, setProofsData] = useState([]);
const [proofsVisible, setProofsVisible] = useState(false); const [proofsVisible, setProofsVisible] = useState(false);
...@@ -65,6 +74,14 @@ const AfterSale = props => { ...@@ -65,6 +74,14 @@ const AfterSale = props => {
const [serviceNoInfo, setServiceNoInfo] = useState({}); const [serviceNoInfo, setServiceNoInfo] = useState({});
const [rejectVisible, setRejectVisible] = useState(false); const [rejectVisible, setRejectVisible] = useState(false);
// 取消订单审核
const [cancelVisible, setCancelVisible] = useState(false);
const [cancelAuditInfo, setCancelAuditInfo] = useState({});
// 取消订单审核详情
const [cancelDetailVisible, setCancelDetailVisible] = useState(false);
const [cancelDetailInfo, setCancelDetailInfo] = useState({});
// 关闭modal // 关闭modal
const closeModal = isReload => { const closeModal = isReload => {
if (isReload === true) { if (isReload === true) {
...@@ -77,6 +94,8 @@ const AfterSale = props => { ...@@ -77,6 +94,8 @@ const AfterSale = props => {
setAppealDetailModal(false); setAppealDetailModal(false);
setAfterVisible(false); setAfterVisible(false);
setLogisticsComModalVisible(false); setLogisticsComModalVisible(false);
setCancelVisible(false);
setCancelDetailVisible(false);
}; };
// 查看申诉详情 // 查看申诉详情
...@@ -187,6 +206,20 @@ const AfterSale = props => { ...@@ -187,6 +206,20 @@ const AfterSale = props => {
setRejectVisible(true); setRejectVisible(true);
}; };
// 取消订单审核
const openCancelAudit = async ({ serviceNo }) => {
// const data = await auditInfoApi({ serviceNo });
setCancelAuditInfo({ serviceNo });
setCancelVisible(true);
};
// 取消订单审核详情
const viewCancelDetail = async ({ serviceNo }) => {
const data = await cancelOrderDetail({ serviceNo });
setCancelDetailInfo(data || []);
setCancelDetailVisible(true);
};
const [form] = Form.useForm(); const [form] = Form.useForm();
const formConfig = getFormConfig({ const formConfig = getFormConfig({
actionRef, actionRef,
...@@ -194,9 +227,13 @@ const AfterSale = props => { ...@@ -194,9 +227,13 @@ const AfterSale = props => {
setTableParams, setTableParams,
setCurrentTab, setCurrentTab,
}); });
const afterTime = [moment().subtract(3, 'month'), moment()];
const FormSearchProps = { const FormSearchProps = {
form, form,
initialValues: {}, initialValues: {
afterTime,
},
formOptions: {}, formOptions: {},
...formConfig, ...formConfig,
}; };
...@@ -205,11 +242,16 @@ const AfterSale = props => { ...@@ -205,11 +242,16 @@ const AfterSale = props => {
const tabChange = tabIndex => { const tabChange = tabIndex => {
setCurrentTab(tabIndex); setCurrentTab(tabIndex);
const { type, dealStatus } = TAB_MAPPING_DATA[tabIndex]; const { type, dealStatus } = TAB_MAPPING_DATA[tabIndex];
form.resetFields();
form.setFieldsValue({ form.setFieldsValue({
...tableParams,
dealStatus, dealStatus,
type, type,
}); });
setTableParams({ ...tableParams, dealStatus, type }); setTableParams({ ...tableParams, dealStatus, type });
// setTimeout(() => {
// form.submit()
// }, 0)
}; };
const columns = getColumns({ const columns = getColumns({
...@@ -223,6 +265,8 @@ const AfterSale = props => { ...@@ -223,6 +265,8 @@ const AfterSale = props => {
refund, refund,
reject, reject,
canEditable, canEditable,
openCancelAudit,
viewCancelDetail,
}); });
// 表格属性 // 表格属性
...@@ -233,11 +277,10 @@ const AfterSale = props => { ...@@ -233,11 +277,10 @@ const AfterSale = props => {
scroll: { x: '100%', y: 500 }, scroll: { x: '100%', y: 500 },
rowKey: r => r.serviceNo, rowKey: r => r.serviceNo,
request: async params => { request: async params => {
console.log(params); const [start, end] = params.afterTime || afterTime;
console.log('搜索', params);
const { current: page, pageSize: size } = params; const { current: page, pageSize: size } = params;
const startDate = params.startDate ? moment(params.startDate).format('YYYY-MM-DD') : ''; const startDate = start ? moment(start).format('YYYY-MM-DD') : '';
const endDate = params.endDate ? moment(params.endDate).format('YYYY-MM-DD') : ''; const endDate = end ? moment(end).format('YYYY-MM-DD') : '';
const requestParams = { const requestParams = {
page, page,
size, size,
...@@ -245,8 +288,20 @@ const AfterSale = props => { ...@@ -245,8 +288,20 @@ const AfterSale = props => {
startDate, startDate,
endDate, endDate,
}; };
delete requestParams.afterTime;
delete requestParams.current;
delete requestParams.pageSize;
const countRes = await getAfterPendingNum({
startDate,
endDate,
});
const res = await searchList(requestParams); const res = await searchList(requestParams);
const { records = [], total } = res.data; const { records = [], total } = res.data;
console.log(countRes);
if (countRes.code === '0000') {
setTabInfoData(countRes.data);
}
return { return {
data: records, data: records,
total, total,
...@@ -278,11 +333,14 @@ const AfterSale = props => { ...@@ -278,11 +333,14 @@ const AfterSale = props => {
tabBarStyle={{ padding: '0 30px' }} tabBarStyle={{ padding: '0 30px' }}
> >
<TabPane key="" tab="全部"></TabPane> <TabPane key="" tab="全部"></TabPane>
<TabPane key="1" tab="仅退款(未发货)待审核0"></TabPane> <TabPane
<TabPane key="2" tab="仅退款待审核8"></TabPane> key="1"
<TabPane key="3" tab="退货退款待审核0"></TabPane> tab={`仅退款(未发货)待审核${tabInfoData.cancelOrderPendingAuditNum}`}
<TabPane key="4" tab="退货入库待审核0"></TabPane> ></TabPane>
<TabPane key="5" tab="已完成0"></TabPane> <TabPane key="2" tab={`仅退款待审核${tabInfoData.refundPendingAuditNum}`}></TabPane>
<TabPane key="3" tab={`退货退款待审核${tabInfoData.returnPendingAuditNum}`}></TabPane>
<TabPane key="4" tab={`退货入库待审核${tabInfoData.returnWaitAuditNum}`}></TabPane>
<TabPane key="5" tab={`已完成${tabInfoData.afterSalseDoneNum}`}></TabPane>
</Tabs> </Tabs>
</div> </div>
<ProTable <ProTable
...@@ -310,6 +368,13 @@ const AfterSale = props => { ...@@ -310,6 +368,13 @@ const AfterSale = props => {
></AppealDetail> ></AppealDetail>
<AfterLog visible={afterVisible} onCancel={closeModal} data={afterList} /> <AfterLog visible={afterVisible} onCancel={closeModal} data={afterList} />
<RejectModal visible={rejectVisible} onCancel={closeModal} serviceNo={serviceNoInfo} /> <RejectModal visible={rejectVisible} onCancel={closeModal} serviceNo={serviceNoInfo} />
<CancelAuditModal visible={cancelVisible} onCancel={closeModal} formData={cancelAuditInfo} />
<CancelDetailTable
visible={cancelDetailVisible}
onCancel={closeModal}
dataSource={cancelDetailInfo}
/>
</PageHeaderWrapper> </PageHeaderWrapper>
); );
}; };
......
...@@ -9,7 +9,7 @@ const { kdspApi } = config; ...@@ -9,7 +9,7 @@ const { kdspApi } = config;
export const searchList = params => export const searchList = params =>
request.post('/api/kdsp/op/afs/shop/list', { request.post('/api/kdsp/op/afs/shop/list', {
prefix: kdspApi, prefix: kdspApi,
data: stringify(_.omitBy(params, v => !v)), data: stringify(_.omitBy(params, v => !v && v !== 0)),
headers: { headers: {
'Content-Type': 'application/x-www-form-urlencoded', 'Content-Type': 'application/x-www-form-urlencoded',
}, },
...@@ -51,6 +51,19 @@ export function orderDetail(params) { ...@@ -51,6 +51,19 @@ export function orderDetail(params) {
}, },
}); });
} }
// 取消售后单详情
export async function cancelOrderDetail(params) {
const data = await request.get('/cancel-order/sku', {
prefix: kdspApi,
params,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
});
return data.data || [];
}
// 售后审核 // 售后审核
export async function shopAudit(params) { export async function shopAudit(params) {
return request.post('/api/kdsp/op/afs/shop/audit', { return request.post('/api/kdsp/op/afs/shop/audit', {
...@@ -58,6 +71,15 @@ export async function shopAudit(params) { ...@@ -58,6 +71,15 @@ export async function shopAudit(params) {
prefix: kdspApi, prefix: kdspApi,
}); });
} }
// 取消订单审核
export async function cancelShopAudit(params) {
return request.post('/cancel-order/audit', {
data: params,
prefix: kdspApi,
});
}
// 查询审核信息 // 查询审核信息
export async function auditInfoApi(params) { export async function auditInfoApi(params) {
return request.get('/api/kdsp/op/afs/back-info', { return request.get('/api/kdsp/op/afs/back-info', {
......
import { Button, notification, Modal, Popover } from 'antd'; import { Button, notification, Modal, Popover } from 'antd';
import React, { useState, useEffect, useRef } from 'react'; import React, { useState, useEffect, useRef } from 'react';
import { PageHeaderWrapper } from '@ant-design/pro-layout'; import { PageHeaderWrapper } from '@ant-design/pro-layout';
import { useLocation } from 'react-router-dom';
import ProTable from '@ant-design/pro-table'; import ProTable from '@ant-design/pro-table';
import { FormInstance } from 'antd/lib/form'; import { FormInstance } from 'antd/lib/form';
import moment from 'moment'; import moment from 'moment';
...@@ -23,8 +24,10 @@ import { ...@@ -23,8 +24,10 @@ import {
const { confirm } = Modal; const { confirm } = Modal;
const TableList = props => { const TableList = props => {
const location = useLocation();
const dateFormat = 'YYYY-MM-DD'; const dateFormat = 'YYYY-MM-DD';
const { permissions } = props; const { permissions } = props;
// 因待发货 和 已发货都使用当前组件,功能且相同,所以只要授权其中一个均可获得发货物流权限 // 因待发货 和 已发货都使用当前组件,功能且相同,所以只要授权其中一个均可获得发货物流权限
const canEditable = const canEditable =
permissions[PENDING_DELIVERY_ORDER.EDITABLE] || permissions[DELIVERY_ORDER.EDITABLE]; permissions[PENDING_DELIVERY_ORDER.EDITABLE] || permissions[DELIVERY_ORDER.EDITABLE];
...@@ -44,6 +47,7 @@ const TableList = props => { ...@@ -44,6 +47,7 @@ const TableList = props => {
const [endTime, setEndTime] = useState(moment()); const [endTime, setEndTime] = useState(moment());
const [orderStatus, setorderStatus] = useState(1); const [orderStatus, setorderStatus] = useState(1);
const [orderNo, setOrderNo] = useState('');
const [endTimeStr, setEndTimeStr] = useState(moment().format(dateFormat)); const [endTimeStr, setEndTimeStr] = useState(moment().format(dateFormat));
const [visibleDelay, setVisibleDelay] = useState(false); const [visibleDelay, setVisibleDelay] = useState(false);
...@@ -133,6 +137,15 @@ const TableList = props => { ...@@ -133,6 +137,15 @@ const TableList = props => {
return ''; return '';
}; };
const PopoverNotice = noticeProps => {
const { time, content } = noticeProps;
return (
<div className={style['popover-notice']}>
{time}{content}
</div>
);
};
const columns = [ const columns = [
{ {
title: '订单ID', title: '订单ID',
...@@ -141,14 +154,32 @@ const TableList = props => { ...@@ -141,14 +154,32 @@ const TableList = props => {
order: 6, order: 6,
width: 250, width: 250,
fixed: 'left', fixed: 'left',
render: (_, record) => ( formItemProps: {
value: orderNo,
onChange(e) {
console.log(e.target.value);
setOrderNo(e.target.value);
},
},
render: (_, record) => {
const { urgeDeliverGoodsList } = record;
const content = () =>
urgeDeliverGoodsList?.map(item => (
<PopoverNotice time={item.time} content={item.content} />
));
return (
<> <>
{_} {_}
<Popover placement="top" title="催发货" content={<>111</>} trigger="click"> {urgeDeliverGoodsList ? (
<Popover placement="top" title="催发货" content={<>{content()}</>} trigger="hover">
<span className={style.urge}></span> <span className={style.urge}></span>
</Popover> </Popover>
) : (
''
)}
</> </>
), );
},
}, },
{ {
title: '订单提醒', title: '订单提醒',
...@@ -156,19 +187,43 @@ const TableList = props => { ...@@ -156,19 +187,43 @@ const TableList = props => {
key: 'orderNotice', key: 'orderNotice',
width: 150, width: 150,
render: (_, record) => { render: (_, record) => {
const { address } = record; const { updateAddressList, platformRemark } = record;
let addressData;
if (updateAddressList) {
addressData = updateAddressList.pop();
}
return ( return (
<div className={style['notice-btn']}> <div className={style['notice-btn']}>
<Popover placement="top" title="收货地址变更" content={<>111</>} trigger="click"> {updateAddressList ? (
<Popover
placement="top"
title="收货地址变更"
content={<PopoverNotice time={addressData.time} content={addressData.content} />}
trigger="hover"
>
<Button block type="primary"> <Button block type="primary">
收货地址变更 收货地址变更
</Button> </Button>
</Popover> </Popover>
<Popover placement="top" title="平台备注" content={<>222</>} trigger="click"> ) : (
''
)}
{platformRemark ? (
<Popover
placement="top"
title="平台备注"
content={
<PopoverNotice time={platformRemark.time} content={platformRemark.content} />
}
trigger="hover"
>
<Button block type="warning"> <Button block type="warning">
平台备注 平台备注
</Button> </Button>
</Popover> </Popover>
) : (
''
)}
</div> </div>
); );
}, },
...@@ -187,7 +242,7 @@ const TableList = props => { ...@@ -187,7 +242,7 @@ const TableList = props => {
hideInTable: true, hideInTable: true,
formItemProps: { formItemProps: {
// eslint-disable-next-line no-nested-ternary // eslint-disable-next-line no-nested-ternary
value: orderStatus ? (orderStatus === 1 ? '' : '') : '', value: orderStatus ? (orderStatus === 1 ? '' : '') : null,
onChange(status) { onChange(status) {
setorderStatus(Number(status)); setorderStatus(Number(status));
}, },
...@@ -395,6 +450,19 @@ const TableList = props => { ...@@ -395,6 +450,19 @@ const TableList = props => {
} }
}, []); }, []);
// 监听路由query参数变化重新发起请求
useEffect(() => {
if (location?.query) {
const { orderNo: orderNumber } = location?.query;
setOrderNo(orderNumber);
if (actionRef.current) {
actionRef.current.reload();
}
} else {
setOrderNo('');
}
}, [location]);
const queryToSendFn = params => { const queryToSendFn = params => {
const transformedParam = { const transformedParam = {
...params, ...params,
...@@ -402,6 +470,7 @@ const TableList = props => { ...@@ -402,6 +470,7 @@ const TableList = props => {
pageNo: params.current, pageNo: params.current,
pageSize: params.pageSize || 20, pageSize: params.pageSize || 20,
timeOutType: orderStatus || '', timeOutType: orderStatus || '',
orderNo,
}; };
return queryToSend(transformedParam); return queryToSend(transformedParam);
}; };
......
...@@ -88,9 +88,15 @@ ...@@ -88,9 +88,15 @@
display: inline-block; display: inline-block;
width: 20px; width: 20px;
height: 20px; height: 20px;
margin-left: 5px;
color: #fff; color: #fff;
line-height: 20px; line-height: 20px;
text-align: center; text-align: center;
background-color: red; background-color: red;
border-radius: 50%; border-radius: 50%;
cursor: pointer;
}
.popover-notice {
max-width: 300px;
} }
import EventEmitter from 'events'; import EventEmitter from 'events';
import { Modal } from 'antd';
class Socket extends EventEmitter { class Socket extends EventEmitter {
event = new EventEmitter(); event = new EventEmitter();
...@@ -11,7 +12,7 @@ class Socket extends EventEmitter { ...@@ -11,7 +12,7 @@ class Socket extends EventEmitter {
this.taskRemindInterval = null; this.taskRemindInterval = null;
this.connected = false; this.connected = false;
this.waitingSendData = []; this.waitingSendData = [];
this.reconnectCount = 0;
return this; return this;
} }
...@@ -73,20 +74,21 @@ class Socket extends EventEmitter { ...@@ -73,20 +74,21 @@ class Socket extends EventEmitter {
// 根据后端返回的状态码做操作 // 根据后端返回的状态码做操作
// 我的项目是当前页面打开两个或者以上,就把当前以打开的socket关闭 // 我的项目是当前页面打开两个或者以上,就把当前以打开的socket关闭
// 否则就20秒重连一次,直到重连成功为止 // 否则就20秒重连一次,直到重连成功为止
if (e.code === '4500') { if (this.reconnectCount > 10) {
this.socket.close(); this.reconnectCount = 0;
} else { return;
}
const reconnect = () => { const reconnect = () => {
clearTimeout(this.taskRemindInterval); clearTimeout(this.taskRemindInterval);
this.taskRemindInterval = setTimeout(() => { this.taskRemindInterval = setTimeout(() => {
if (!this.connected) { if (!this.connected) {
this.reconnectCount++;
this.connection(); this.connection();
reconnect(); reconnect();
} }
}, 5000); }, 2000);
}; };
reconnect(); reconnect();
}
}; };
onerror = e => { onerror = e => {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment