Commit 7534953c authored by 李腾's avatar 李腾

feat: 完成售后订单列表逻辑

parent 17b8b15c
...@@ -148,24 +148,24 @@ export default { ...@@ -148,24 +148,24 @@ export default {
}, },
{ {
title: '商户管理后台', title: '商户管理后台',
path: '/afterSaleManageNew', path: '/afterSaleManageOld',
name: 'afterSaleManageNew', name: 'afterSaleManageOld',
icon: 'smile', icon: 'smile',
component: './AfterSaleManageNew/index', component: './AfterSaleManageOld/index',
}, },
{ {
title: '商户管理后台', title: '商户管理后台',
path: '/auditPending', path: '/auditPending',
name: 'auditPending', name: 'auditPending',
icon: 'smile', icon: 'smile',
component: './AfterSaleManage/Pending', component: './AfterSaleManageOld/Pending',
}, },
{ {
title: '商户管理后台', title: '商户管理后台',
path: '/passAudit', path: '/passAudit',
name: 'passAudit', name: 'passAudit',
icon: 'smile', icon: 'smile',
component: './AfterSaleManage/PassAudit', component: './AfterSaleManageOld/PassAudit',
}, },
{ {
title: '商户管理后台', title: '商户管理后台',
......
.tab-pane {
flex: 1;
}
.filter-box {
display: flex;
margin-top: 15px;
padding-right: 25px;
&__content {
flex: 1;
}
// &__actions{
// }
}
.complex-list { .complex-list {
height: 500px; height: 500px;
margin-top: 20px;
padding-right: 25px;
overflow-y: auto; overflow-y: auto;
border: 1px solid #efefef;
& :first-child { & :first-child {
margin: 0; margin: 0;
} }
&__item { &__item {
margin-top: 15px; margin-top: 15px;
border: 1px solid #efefef;
&--header { &--header {
display: flex; display: flex;
width: 100%; width: 100%;
height: 40px; height: 40px;
padding: 0 20px; padding: 0 15px;
line-height: 40px; line-height: 40px;
background: #f8f8f8; background: #fff;
.orderNumber { border-bottom: 1px solid #efefef;
.order-number,
.time {
flex: 1; flex: 1;
padding: 0 20px; padding-right: 20px;
color: #999;
} }
.notice {
color: green; .read-status {
&--read {
color: #999;
}
} }
} }
&--body { &--body {
...@@ -37,16 +60,30 @@ ...@@ -37,16 +60,30 @@
&--footer { &--footer {
display: flex; display: flex;
justify-content: end;
padding: 0 15px;
border-top: 1px solid #efefef; border-top: 1px solid #efefef;
border-bottom: 1px solid #efefef;
.actions { .actions {
display: flex; display: flex;
width: 100%;
margin-left: 10px; margin-left: 10px;
line-height: 40px; line-height: 40px;
a { a {
margin-left: 15px; position: relative;
display: block;
flex: 1;
color: #ff1515;
font-weight: 400;
&::after {
position: absolute;
top: 50%;
right: 10px;
display: block;
width: 0;
height: 0;
margin-top: -3px;
border: 6px solid transparent;
border-left: 8px solid #999;
content: '';
}
} }
} }
} }
...@@ -54,5 +91,7 @@ ...@@ -54,5 +91,7 @@
} }
.pagination { .pagination {
width: 100%;
padding: 25px;
text-align: right; text-align: right;
} }
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { Badge, notification } from 'antd'; import { Badge, notification, Spin } from 'antd';
import { CloseOutlined } from '@ant-design/icons'; import { CloseOutlined } from '@ant-design/icons';
import classNames from 'classnames'; import classNames from 'classnames';
import { connect } from 'dva'; import { connect } from 'dva';
...@@ -21,21 +21,26 @@ const Horn = props => { ...@@ -21,21 +21,26 @@ const Horn = props => {
}; };
const Message = props => { const Message = props => {
const { toggle, animationClass, messageData, openComplex, onMark } = props; const { toggle, animationClass, messageData, openComplex, onMark, loading } = props;
const ReminderItem = args => { const ReminderItem = args => {
const { item } = args; const { item } = args;
const { orderNo, createdAt } = JSON.parse(item.sendContent || '{}'); let message = {};
try {
message = JSON.parse(item.sendContent || '{}');
} catch (e) {
console.error('消息数据格式错误');
}
return ( return (
<div className={styles.item}> <div className={styles.item}>
<div className={styles.info}> <div className={styles.info}>
<span className={styles['order-number']}>{orderNo}</span> <span className={styles['order-number']}>{message.orderNo}</span>
<span className={styles['mark-read']} onClick={() => onMark([item.id])}> <span className={styles['mark-read']} onClick={() => onMark([item.id])}>
标记为已读 标记为已读
</span> </span>
</div> </div>
<div className={styles.time}> <div className={styles.time}>
<span>{createdAt}</span> <span>{message.createdAt}</span>
</div> </div>
<div className={styles.notice}> <div className={styles.notice}>
<a>您有新的xxxxx订单,请查看</a> <a>您有新的xxxxx订单,请查看</a>
...@@ -55,15 +60,17 @@ const Message = props => { ...@@ -55,15 +60,17 @@ const Message = props => {
</div> </div>
</div> </div>
<div className={styles['message-reminder__body']}> <div className={styles['message-reminder__body']}>
<div className={styles['message-reminder__body--list']}> <Spin spinning={loading}>
{messageData.length ? ( <div className={styles['message-reminder__body--list']}>
messageData {messageData.length ? (
.filter((e, i) => i < 10) messageData
.map(item => <ReminderItem key={item.id} item={item} />) .filter((e, i) => i < 10)
) : ( .map(item => <ReminderItem key={item.id} item={item} />)
<Empty text="暂无数据" /> ) : (
)} <Empty text="暂无数据" />
</div> )}
</div>
</Spin>
</div> </div>
<div className={styles['message-reminder__footer']}> <div className={styles['message-reminder__footer']}>
<div className={styles['message-reminder__footer--actions']}> <div className={styles['message-reminder__footer--actions']}>
...@@ -87,6 +94,7 @@ const Message = props => { ...@@ -87,6 +94,7 @@ const Message = props => {
const Simple = props => { const Simple = props => {
const { dispatch, unReadCount, complexRef, unReadData } = props; const { dispatch, unReadCount, complexRef, unReadData } = props;
const [visible, setVisible] = useState(false); const [visible, setVisible] = useState(false);
const [loading, setLoading] = useState(false);
const [count, setCount] = useState(0); const [count, setCount] = useState(0);
const [hornClass, setHornClass] = useState(''); const [hornClass, setHornClass] = useState('');
const [messageClass, setMessageClass] = useState(''); const [messageClass, setMessageClass] = useState('');
...@@ -110,7 +118,9 @@ const Simple = props => { ...@@ -110,7 +118,9 @@ const Simple = props => {
bussinessId: userInfo.supplierCode, bussinessId: userInfo.supplierCode,
readStatus: 0, readStatus: 0,
}; };
setLoading(true);
const res = await apiGetBussinessMsgList(data, params); const res = await apiGetBussinessMsgList(data, params);
setLoading(false);
if (res.code !== '0000') { if (res.code !== '0000') {
notification.error(res.msg); notification.error(res.msg);
return; return;
...@@ -135,6 +145,9 @@ const Simple = props => { ...@@ -135,6 +145,9 @@ const Simple = props => {
// 标记已读信息 // 标记已读信息
const onMark = idList => { const onMark = idList => {
if (!idList.length) {
return;
}
const payload = { const payload = {
channelId: CHANNEL_ID, channelId: CHANNEL_ID,
bussinessId: userInfo.supplierCode, bussinessId: userInfo.supplierCode,
...@@ -143,6 +156,9 @@ const Simple = props => { ...@@ -143,6 +156,9 @@ const Simple = props => {
dispatch({ dispatch({
type: 'messageReminder/setMarkRead', type: 'messageReminder/setMarkRead',
payload, payload,
options: {
setLoading,
},
}); });
}; };
...@@ -175,6 +191,7 @@ const Simple = props => { ...@@ -175,6 +191,7 @@ const Simple = props => {
messageData, messageData,
openComplex, openComplex,
onMark, onMark,
loading,
}; };
// 隐藏消息提醒 // 隐藏消息提醒
......
...@@ -14,6 +14,7 @@ import Authorized from '@/utils/Authorized'; ...@@ -14,6 +14,7 @@ import Authorized from '@/utils/Authorized';
import RightContent from '@/components/GlobalHeader/RightContent'; import RightContent from '@/components/GlobalHeader/RightContent';
import MessageReminder from '@/components/MessageReminder'; import MessageReminder from '@/components/MessageReminder';
import { getAuthorityFromRouter } from '@/utils/utils'; import { getAuthorityFromRouter } from '@/utils/utils';
import { getSocketUrl } from '@/services/messageReminder';
import logo from '../assets/logo.png'; import logo from '../assets/logo.png';
import style from './BasicLayout.less'; import style from './BasicLayout.less';
...@@ -60,7 +61,7 @@ const BasicLayout = props => { ...@@ -60,7 +61,7 @@ const BasicLayout = props => {
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({
url: `ws://ws-sc.liangkebang.net/ws?token=${token}&channelId=${channelId}`, url: getSocketUrl({ token, channelId }),
}); });
socket.connection(); socket.connection();
...@@ -69,27 +70,28 @@ const BasicLayout = props => { ...@@ -69,27 +70,28 @@ const BasicLayout = props => {
}); });
socket.event.on('message', msg => { socket.event.on('message', msg => {
console.log(msg);
dispatch({ dispatch({
type: 'messageReminder/setUnReadData', type: 'messageReminder/setUnReadData',
payload: JSON.parse(msg.data), payload: [JSON.parse(msg.data)],
}); });
}); });
let a = 100000000000; // let a = 100000000000;
setInterval(() => { // setInterval(() => {
a++; // a++;
socket.sendMessage([ // socket.sendMessage(
{ // {
id: a, // id: a,
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", "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',
}, // },
]); // );
}, 5000); // }, 5000);
if (dispatch) { if (dispatch) {
dispatch({ dispatch({
type: 'settings/getSetting', type: 'settings/getSetting',
...@@ -224,6 +226,7 @@ const BasicLayout = props => { ...@@ -224,6 +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" /> */}
</ProLayout> </ProLayout>
); );
}; };
......
...@@ -16,9 +16,16 @@ const MessageReminderModel = { ...@@ -16,9 +16,16 @@ const MessageReminderModel = {
}); });
}); });
}, },
*setMarkRead({ payload, options }, { put, call }) { *setMarkRead({ payload, options = {} }, { put, call }) {
// const res = yield call(apiUpdageBusinessMsgStatus, payload) const { setLoading } = options;
if (setLoading) {
setLoading(true);
}
const res = yield call(apiUpdageBusinessMsgStatus, payload);
// console.log(res) // console.log(res)
if (setLoading) {
setLoading(false);
}
yield put({ yield put({
type: 'updateUnReadData', type: 'updateUnReadData',
payload, payload,
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
/* eslint-disable guard-for-in */ /* eslint-disable guard-for-in */
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { Modal, Timeline, Button } from 'antd'; import { Modal, Timeline, Button } from 'antd';
import styles from '../styles.less'; import styles from '../index.less';
const LogisticsCom = props => { const LogisticsCom = props => {
const { visible, onCancel, data } = props; const { visible, onCancel, data } = props;
......
import React, { useState, forwardRef, useImperativeHandle, useEffect } from 'react';
import { Modal, Timeline, notification, Spin } from 'antd';
import { getLogisticsRecord } from '../services';
const LogisticsRecordModal = (props, ref) => {
// const { } = props;
const [visible, setVisible] = useState(false);
const [result, setResult] = useState({});
const [loading, setLoading] = useState(false);
const getRecordList = async orderNo => {
const tempObj = {
detailList: [],
key: Date.now(),
};
setLoading(true);
const res = await getLogisticsRecord({ orderNo });
setLoading(false);
if (!res) {
notification.info({ message: '暂无物流信息' });
return;
}
const { logisticsName, logisticsBillNo, logisticsList = [] } = res.data;
tempObj.expressCompanyName = logisticsName;
tempObj.deliveryNo = logisticsBillNo;
logisticsList.forEach(v => {
tempObj.detailList = [...tempObj.detailList, ...v.detailList];
});
setResult(tempObj);
};
const open = orderNo => {
setVisible(true);
getRecordList(orderNo);
};
const onCancel = () => {
setVisible(false);
setResult([]);
};
useImperativeHandle(ref, () => ({
open,
}));
const modalProps = {
title: '查看物流',
visible,
onCancel,
destroyOnClose: true,
bodyStyle: { maxHeight: '600px', minHeight: '200px', overflow: 'auto' },
footer: null,
};
const emptyStyle = {
textAlign: 'center',
padding: '30px 0',
color: '#999',
};
return (
<Modal {...modalProps}>
<Spin spinning={loading}>
{result.detailList?.length ? (
<Timeline>
{result?.detailList?.map((item, index) => (
<Timeline.Item color={index > 0 ? 'gray' : 'blue'} key={index.toString()}>
<p>{item.desc}</p>
<p>{item.logisticsTime}</p>
</Timeline.Item>
))}
</Timeline>
) : (
<div style={emptyStyle}>暂无物流信息</div>
)}
</Spin>
</Modal>
);
};
export default forwardRef(LogisticsRecordModal);
const LogisticsCom = props => {
const { modalVisible, onCancel } = props;
const [result, setResult] = useState({});
useEffect(() => {
setResult(props.value);
});
return (
<Modal
destroyOnClose
title={`${
result?.expressCompanyName
? `${result?.expressCompanyName}-${result?.deliveryNo}`
: '物流信息'
}`}
visible={modalVisible}
onCancel={() => onCancel()}
onOk={() => onCancel()}
afterClose={() => setResult({})}
bodyStyle={{ maxHeight: '600px', minHeight: '200px', overflow: 'auto' }}
footer={[]}
>
{result?.detailList?.length ? (
<Timeline>
{result?.detailList?.map((item, index) => (
// eslint-disable-next-line react/no-array-index-key
<Timeline.Item color={index > 0 ? 'gray' : 'blue'} key={index}>
<p>{item.desc}</p>
<p>{item.logisticsTime}</p>
</Timeline.Item>
))}
</Timeline>
) : (
'暂无物流信息'
)}
</Modal>
);
};
import React, { useState } from 'react'; import React, { useState } from 'react';
import { Modal } from 'antd'; import { Modal } from 'antd';
import style from '../styles.less'; import style from '../index.less';
export default props => { export default props => {
const { visible, onCancel, data } = props; const { visible, onCancel, data } = props;
......
This diff is collapsed.
import { Tabs } from 'antd'; import React, { useRef, useState, useEffect } from 'react';
import React from 'react'; import { Tabs, notification, Form, Modal } from 'antd';
import { PageHeaderWrapper } from '@ant-design/pro-layout'; import { PageHeaderWrapper } from '@ant-design/pro-layout';
import ProTable from '@ant-design/pro-table';
import { AFTER_SALE_ORDER } from '@/../config/permission.config'; import { AFTER_SALE_ORDER } from '@/../config/permission.config';
import { connect } from 'dva'; import { connect } from 'dva';
import Pending from './Pending'; import { FormSearch } from '@/components/FormSearch';
import PassAudit from './PassAudit'; import moment from 'moment';
import AuditModal from './components/auditModal';
import DetailTable from './components/detailTable';
import ProofsModal from './components/proofsModal';
import AppealDetail from '@/pages/afterSale/components/detail';
import AfterLog from './components/AfterLog';
import RejectModal from './components/rejectModal';
import LogisticsCom from '../orderManage/pendingDeliveryOrder/components/LogisticsCom';
import { getColumns, getFormConfig, TAB_MAPPING_DATA } from './data.js';
import { getDetail } from '@/pages/afterSale/appeal/services';
import {
searchList,
logisticsIntercept,
orderDetail,
getOpLog,
auditInfoApi,
trackInfo,
shopCheck,
getAfterPendingNum,
} from './services';
import styles from './index.less';
const { TabPane } = Tabs; const { TabPane } = Tabs;
const { confirm } = Modal;
function AfterSale(props) { const AfterSale = props => {
const { permissions } = props; const { permissions } = props;
const canEditable = permissions[AFTER_SALE_ORDER.EDITABLE]; const canEditable = permissions[AFTER_SALE_ORDER.EDITABLE];
const actionRef = useRef();
const formRef = useRef();
const [tableParams, setTableParams] = useState({});
const [currentTab, setCurrentTab] = useState('');
const [appealDetailModal, setAppealDetailModal] = useState(false);
const [selectedRow, setSelectedRow] = useState({});
const [tabInfoData, setTabInfoData] = useState({});
// 申诉
const [proofsData, setProofsData] = useState([]);
const [proofsVisible, setProofsVisible] = useState(false);
// 详情
const [detailVisible, setDetailVisible] = useState(false);
const [detailInfo, setDetailInfo] = useState([]);
// 售后操作记录
const [afterVisible, setAfterVisible] = useState(false);
const [afterList, setAfterList] = useState([]);
// 审核
const [visible, setVisible] = useState(false);
const [auditInfo, setAuditInfo] = useState({});
// 查看物流
const [LogisticsComList, setLogisticsComList] = useState({});
const [logisticsComModalVisible, setLogisticsComModalVisible] = useState(false);
// 驳回
const [serviceNoInfo, setServiceNoInfo] = useState({});
const [rejectVisible, setRejectVisible] = useState(false);
// 关闭modal
const closeModal = isReload => {
if (isReload === true) {
// eslint-disable-next-line no-unused-expressions
actionRef.current?.reload?.();
}
setVisible(false);
setDetailVisible(false);
setProofsVisible(false);
setAppealDetailModal(false);
setAfterVisible(false);
setLogisticsComModalVisible(false);
};
// 查看申诉详情
const viewAppeal = async r => {
const detailData = await getDetail({ appealNo: r.appealNo });
setAppealDetailModal(true);
setSelectedRow(detailData);
};
// 查看凭证
const viewProofs = proofs => {
if (!proofs) {
notification.warning({ message: '该订单没有凭证' });
return;
}
const list = proofs.replace(/(\uff1b|\uff0c|\u003b)/g, ',').split(',');
setProofsData(list);
setProofsVisible(true);
};
// 审核
const openAudit = async ({ serviceNo, serviceType, orderNo }) => {
const data = await auditInfoApi({ serviceNo });
setAuditInfo({ ...data?.data, serviceNo, serviceType, orderNo });
setVisible(true);
};
// 查看物流
const handleCom = async ({ expressCompanyCode, deliveryNo }) => {
const tempObj = {
detailList: [],
key: Date.now(),
};
const data = await trackInfo({ expressCompanyCode, logisticsNo: deliveryNo });
if (!data) {
notification.info({ message: '暂无物流信息' });
return;
}
tempObj.expressCompanyName = data.logisticsName;
tempObj.deliveryNo = data.logisticsBillNo;
if (data.logisticsList?.length) {
data.logisticsList.forEach(v => {
tempObj.detailList = [...tempObj.detailList, ...v.detailList];
});
}
setLogisticsComModalVisible(true);
setLogisticsComList(tempObj);
};
// 物流拦截
const openLogistics = r => {
confirm({
title: '温馨提示',
okText: '确认拦截',
cancelText: '取消拦截',
content: (
<div>
请48小时内自行联系物流公司进行物流拦截,系统监测拦截成功后
<span className={styles.redTipBold}>自动同意</span>退款
</div>
),
async onOk() {
const data = await logisticsIntercept({ serviceNo: r.serviceNo });
if (data.businessCode === '0000') {
notification.success({ message: '拦截成功' });
actionRef.current.reload();
} else {
notification.error({ message: data.msg || '拦截失败' });
}
},
onCancel() {
console.log('Cancel');
},
});
};
// 查看
const viewDetail = async ({ serviceNo }) => {
const res = await orderDetail({ serviceNo });
const data = res.data || [];
setDetailInfo(data);
setDetailVisible(true);
};
// 查看售后操作日志
const viewLog = async r => {
const data = await getOpLog(r.serviceNo);
if (data?.data?.length) {
setAfterList(data.data);
setAfterVisible(true);
}
};
// 已退款/允许退款
const refund = async ({ serviceNo }) => {
const data = await shopCheck({
serviceNo,
auditResult: 1,
});
if (data.businessCode === '0000') {
notification.success({ message: '操作成功' });
closeModal(true);
}
};
// 驳回
const reject = async ({ serviceNo }) => {
setServiceNoInfo(serviceNo);
setRejectVisible(true);
};
const [form] = Form.useForm();
const formConfig = getFormConfig({
actionRef,
tableParams,
setTableParams,
setCurrentTab,
});
const FormSearchProps = {
form,
initialValues: {},
formOptions: {},
...formConfig,
};
// tab选项框回调
const tabChange = tabIndex => {
setCurrentTab(tabIndex);
const { type, dealStatus } = TAB_MAPPING_DATA[tabIndex];
form.setFieldsValue({
dealStatus,
type,
});
setTableParams({ ...tableParams, dealStatus, type });
};
const columns = getColumns({
openAudit,
viewAppeal,
viewProofs,
openLogistics,
viewDetail,
viewLog,
handleCom,
refund,
reject,
canEditable,
});
// 表格属性
const tableProps = {
columns,
params: tableParams,
bordered: true,
scroll: { x: '100%', y: 500 },
rowKey: r => r.serviceNo,
request: async params => {
console.log(params);
console.log('搜索', params);
const { current: page, pageSize: size } = params;
const startDate = params.startDate ? moment(params.startDate).format('YYYY-MM-DD') : '';
const endDate = params.endDate ? moment(params.endDate).format('YYYY-MM-DD') : '';
const requestParams = {
page,
size,
...params,
startDate,
endDate,
};
const res = await searchList(requestParams);
const { records = [], total } = res.data;
return {
data: records,
total,
};
},
toolBarRender: null,
};
const getPendingNum = async () => {
const params = {
startDate: new Date('2020/01/01 00:00:00'),
endDate: new Date(),
};
const res = await getAfterPendingNum(params);
console.log(res);
};
useEffect(() => {
getPendingNum();
}, []);
return ( return (
<PageHeaderWrapper> <PageHeaderWrapper>
<Tabs defaultActiveKey="1"> <FormSearch {...FormSearchProps} />
<TabPane tab="未审核" key="1"> <div className={styles['tab-box']}>
<Pending canEditable={canEditable} /> <Tabs
</TabPane> activeKey={currentTab}
<TabPane tab="已审核" key="2"> onChange={tabChange}
<PassAudit canEditable={canEditable} /> size="large"
</TabPane> tabBarStyle={{ padding: '0 30px' }}
</Tabs> >
<TabPane key="" tab="全部"></TabPane>
<TabPane key="1" tab="仅退款(未发货)待审核0"></TabPane>
<TabPane key="2" tab="仅退款待审核8"></TabPane>
<TabPane key="3" tab="退货退款待审核0"></TabPane>
<TabPane key="4" tab="退货入库待审核0"></TabPane>
<TabPane key="5" tab="已完成0"></TabPane>
</Tabs>
</div>
<ProTable
{...tableProps}
actionRef={actionRef}
formRef={formRef}
search={false}
// toolBarRender={false}
/>
<AuditModal visible={visible} onCancel={closeModal} formData={auditInfo} />
<DetailTable visible={detailVisible} onCancel={closeModal} dataSource={detailInfo} />
<ProofsModal visible={proofsVisible} onCancel={closeModal} data={proofsData} />
<LogisticsCom
onSubmit={closeModal}
onCancel={closeModal}
modalVisible={logisticsComModalVisible}
value={LogisticsComList}
key={LogisticsComList.key}
/>
<AppealDetail
data={selectedRow}
modalVisible={appealDetailModal}
onCancel={closeModal}
></AppealDetail>
<AfterLog visible={afterVisible} onCancel={closeModal} data={afterList} />
<RejectModal visible={rejectVisible} onCancel={closeModal} serviceNo={serviceNoInfo} />
</PageHeaderWrapper> </PageHeaderWrapper>
); );
} };
export default connect(({ menu }) => ({ export default connect(({ menu }) => ({
permissions: menu.permissions, permissions: menu.permissions,
......
...@@ -6,42 +6,50 @@ import _ from 'lodash'; ...@@ -6,42 +6,50 @@ import _ from 'lodash';
const { kdspApi } = config; const { kdspApi } = config;
// 分页查询所有数据 // 分页查询所有数据
export async function searchList(params, queryStatus) { export const searchList = params =>
const param = { request.post('/api/kdsp/op/afs/shop/list', {
...params,
pageNo: params.current,
pageSize: params.pageSize || 20,
queryStatus,
};
const data = await request.post('/api/kdsp/op/afs/shop/list', {
prefix: kdspApi, prefix: kdspApi,
data: stringify(_.omitBy(param, v => !v)), data: stringify(_.omitBy(params, v => !v)),
headers: { headers: {
'Content-Type': 'application/x-www-form-urlencoded', 'Content-Type': 'application/x-www-form-urlencoded',
}, },
}); });
if (data.data) {
return { // export async function searchList(params, queryStatus) {
total: data.data.total, // const param = {
data: data.data.records, // ...params,
}; // pageNo: params.current,
} // pageSize: params.pageSize || 20,
return { // queryStatus,
total: 0, // };
data: [], // const data = await request.post('/api/kdsp/op/afs/shop/list', {
}; // prefix: kdspApi,
} // data: stringify(_.omitBy(param, v => !v)),
// headers: {
// 'Content-Type': 'application/x-www-form-urlencoded',
// },
// });
// if (data.data) {
// return {
// total: data.data.total,
// data: data.data.records,
// };
// }
// return {
// total: 0,
// data: [],
// };
// }
// 售后单详情 // 售后单详情
export async function orderDetail(params) { export function orderDetail(params) {
const data = await request.get('/api/kdsp/op/afs/sku', { return request.get('/api/kdsp/op/afs/sku', {
prefix: kdspApi, prefix: kdspApi,
params, params,
headers: { headers: {
'Content-Type': 'application/x-www-form-urlencoded', 'Content-Type': 'application/x-www-form-urlencoded',
}, },
}); });
return data.data || [];
} }
// 售后审核 // 售后审核
export async function shopAudit(params) { export async function shopAudit(params) {
...@@ -93,3 +101,18 @@ export async function getOpLog(params) { ...@@ -93,3 +101,18 @@ export async function getOpLog(params) {
prefix: kdspApi, prefix: kdspApi,
}); });
} }
// 查询物流记录信息
export async function getLogisticsRecord(params) {
return request.get(`/api/kdsp/op/logistics/kd100/track-list?orderNo=${params.orderNo}`, {
prefix: kdspApi,
});
}
// 查询售后待办数量
export function getAfterPendingNum(data) {
return request.post('/api/kdsp/op/afs/getPendingNum', {
prefix: kdspApi,
data,
});
}
import { Tag, Badge, Statistic, Button } from 'antd';
import React from 'react';
import moment from 'moment';
import { SEARCH_TYPE } from '@/components/FormSearch';
const { Countdown } = Statistic;
// 商户审核中/商户审核拒绝/待填写退货物流信息/待退货入库/退货拒收/退款成功/用户撤销”
// 仅退款(未发货)/仅退款/退货退款,新增【仅退款(未发货)】即取消订单待审核
// 售后类型
const AFTER_TYPE = [
{
value: '1',
name: '商户审核中',
},
{
value: '2',
name: '商户审核拒绝',
},
{
value: '3',
name: '待填写退货物流信息',
},
{
value: '4',
name: '待退货入库',
},
{
value: '5',
name: '退货拒收',
},
{
value: '5',
name: '退款成功',
},
{
value: '6',
name: '用户撤销”',
},
];
// 售后状态
const AFTER_STATUS = [
{
value: '1',
name: '仅退款(未发货)',
},
{
value: '1',
name: '仅退款',
},
{
value: '1',
name: '退货退款',
},
];
export const getFormConfig = (props = {}) => {
const { setTableParams } = props;
return {
formConfig: [
{
type: SEARCH_TYPE.INPUT,
label: '订单ID',
bindKey: 'orderNo',
column: 5,
},
{
type: SEARCH_TYPE.INPUT,
label: '售后单ID',
bindKey: 'serviceNo',
column: 5,
},
{
type: SEARCH_TYPE.SELECT,
label: '售后状态',
column: 5,
bindKey: 'dealStatus',
options: AFTER_STATUS,
},
{
type: SEARCH_TYPE.SELECT,
label: '售后类型',
column: 5,
bindKey: 'type',
options: AFTER_TYPE,
},
{
type: SEARCH_TYPE.INPUT,
label: '收货人姓名',
column: 5,
bindKey: 'receiverName',
},
{
type: SEARCH_TYPE.INPUT,
label: '收货人手机号',
column: 5,
bindKey: 'receiverPhone',
},
{
type: SEARCH_TYPE.DATE_PICKER,
label: '订单开始日期',
column: 5,
bindKey: 'startDate',
},
{
type: SEARCH_TYPE.DATE_PICKER,
label: '订单结束日期',
column: 5,
bindKey: 'endDate',
},
],
btnConfig: [
{
label: '筛选',
clickType: 'submit',
onClick: ({ type, params }) => {
setTableParams(params);
},
},
{
label: '重置',
type: '',
clickType: 'reset',
onClick: () => {
setTableParams({});
},
},
],
};
};
export const appealType = {
1: '已申诉',
0: '未申诉',
};
export const getColumns = props => {
const {
openAudit,
viewAppeal,
viewProofs,
openLogistics,
viewDetail,
viewLog,
canEditable,
} = props;
return [
{
title: '审核倒计时',
dataIndex: 'serviceTime',
key: 'serviceTime',
hideInSearch: true,
width: 150,
render: (val, record) => {
const serviceTime = moment(record.approvalEndTime).valueOf();
return (
<Countdown
format="HH时mm分ss秒"
value={serviceTime}
valueStyle={{ color: 'red', fontSize: '14px' }}
/>
);
},
},
{
title: '售后状态',
dataIndex: 'serviceStatus',
hideInSearch: true,
width: 120,
},
{
title: '售后类型',
dataIndex: 'serviceType',
hideInSearch: true,
width: 120,
render: serviceType => {
if (+serviceType === 1) {
return <span style={{ color: '#ff1616' }}>仅退款</span>;
}
return <span>退货退款</span>;
},
},
{
title: '订单ID',
dataIndex: 'orderNo',
hideInTable: true,
width: 200,
},
{
title: '售后单ID',
dataIndex: 'serviceNo',
width: 300,
render: (serviceNo, r) => (
<div>
{r.timeout ? <Tag color="red">{serviceNo}</Tag> : serviceNo}
{<Badge count={r.reminderFlag ? '' : ''} size="default" />}
</div>
),
},
{
title: '订单ID',
dataIndex: 'orderNo',
hideInSearch: true,
width: 300,
},
{
title: '售后状态',
dataIndex: 'dealStatus',
hideInTable: true,
valueEnum: {
0: '待审核',
10: '三方审核中',
11: '三方审核通过',
12: '三方审核拒绝',
13: '客服审核通过',
14: '商户审核中',
15: '商户审核通过',
16: '商户审核拒绝',
20: '审核拒绝',
21: '申诉中',
30: '待填写退货物流信息',
40: '待退货入库',
50: '退货拒收',
60: '待退款',
61: '退货处理中',
70: '售后成功',
99: '用户取消',
},
width: 100,
},
{
title: '售后类型',
dataIndex: 'type',
hideInTable: true,
width: 120,
valueEnum: {
1: '仅退款',
2: '退货退款',
},
},
{
title: '收货人姓名',
dataIndex: 'receiverName',
width: 200,
},
{
title: '收货人手机号',
dataIndex: 'receiverPhone',
width: 200,
},
{
title: '收货人地址',
dataIndex: 'receiveAddress',
width: 200,
hideInSearch: true,
},
{
title: '订单开始时间',
width: 120,
dataIndex: 'startDate',
key: 'startDate',
valueType: 'date',
hideInTable: true,
},
{
title: '订单结束时间',
width: 120,
dataIndex: 'endDate',
key: 'endDate',
valueType: 'date',
hideInTable: true,
},
{
title: '售后原因',
dataIndex: 'serviceReason',
hideInSearch: true,
width: 200,
},
{
title: '售后发生时间',
dataIndex: 'serviceTime',
hideInSearch: true,
width: 200,
},
{
title: '超时时间',
dataIndex: 'overtime',
hideInSearch: true,
width: 200,
},
{
title: '是否催办',
dataIndex: 'reminderFlag',
hideInSearch: true,
width: 120,
valueEnum: {
true: '',
false: '',
},
},
{
title: '是否同意售后',
dataIndex: 'isAgree',
hideInSearch: true,
width: 120,
},
{
title: '拒绝原因',
dataIndex: 'refuseReason',
hideInSearch: true,
width: 200,
},
{
title: '售后凭证',
dataIndex: 'proofs',
hideInSearch: true,
width: 100,
render: (val, r) => <a onClick={() => viewProofs(r.proofs)}>查看凭证</a>,
},
{
title: '售后申诉',
dataIndex: 'appealFlag',
valueEnum: appealType,
hideInSearch: true,
width: 120,
render: (appealFlag, r) => {
if (appealFlag) {
return <a onClick={() => viewAppeal(r)}>已申诉</a>;
}
return <div>未申诉</div>;
},
},
{
title: '操作',
hideInSearch: true,
dataIndex: 'action',
width: 250,
fixed: 'right',
render: (val, r) => {
const operations = [
<Button key="link1" onClick={() => openAudit(r)} className="mr10 mt10" type="primary">
审核
</Button>,
<Button
disabled={r.serviceType !== 1 || (r.serviceType === 1 && r.intercept)}
onClick={() => openLogistics(r)}
className="mr10 mt10"
type="primary"
>
物流拦截
</Button>,
<Button className="mr10 mt10" key="link" onClick={() => viewDetail(r)} type="primary">
订单详情
</Button>,
<Button className="mr10 mt10" type="primary" onClick={() => viewLog(r)}>
查看记录
</Button>,
];
// 不可编辑直接隐藏可操作按钮
if (!canEditable) {
return [operations[2], operations[3]];
}
// 服务订单删除物流拦截
if (!['vip', 'self'].includes(r.supplierType)) {
return [operations[0], operations[2], operations[3]];
}
return operations;
},
},
];
};
import React, { useRef, useState } from 'react';
import { Tabs, notification, Form, Modal } from 'antd';
import { PageHeaderWrapper } from '@ant-design/pro-layout';
import ProTable from '@ant-design/pro-table';
import { AFTER_SALE_ORDER } from '@/../config/permission.config';
import { connect } from 'dva';
import { FormSearch } from '@/components/FormSearch';
import moment from 'moment';
import AuditModal from './components/auditModal';
import DetailTable from './components/detailTable';
import ProofsModal from './components/proofsModal';
import AppealDetail from '@/pages/afterSale/components/detail';
import AfterLog from './components/AfterLog';
import { getColumns, getFormConfig } from './data.js';
import { getDetail } from '@/pages/afterSale/appeal/services';
import { searchList, logisticsIntercept, orderDetail, getOpLog, auditInfoApi } from './services';
import styles from './index.less';
const { TabPane } = Tabs;
const { confirm } = Modal;
const AfterSale = props => {
const { permissions } = props;
const canEditable = permissions[AFTER_SALE_ORDER.EDITABLE];
const actionRef = useRef();
const formRef = useRef();
const [tableParams, setTableParams] = useState({});
const [appealDetailModal, setAppealDetailModal] = useState(false);
const [selectedRow, setSelectedRow] = useState({});
// 申诉
const [proofsData, setProofsData] = useState([]);
const [proofsVisible, setProofsVisible] = useState(false);
// 详情
const [detailVisible, setDetailVisible] = useState(false);
const [detailInfo, setDetailInfo] = useState([]);
// 售后操作记录
const [afterVisible, setAfterVisible] = useState(false);
const [afterList, setAfterList] = useState([]);
// 审核
const [visible, setVisible] = useState(false);
const [auditInfo, setAuditInfo] = useState({});
// 关闭modal
const closeModal = isReload => {
if (isReload === true) {
// eslint-disable-next-line no-unused-expressions
actionRef.current?.reload?.();
}
setVisible(false);
setDetailVisible(false);
setProofsVisible(false);
setAppealDetailModal(false);
setAfterVisible(false);
};
// 查看申诉详情
const viewAppeal = async r => {
const detailData = await getDetail({ appealNo: r.appealNo });
setAppealDetailModal(true);
setSelectedRow(detailData);
};
// 查看凭证
const viewProofs = proofs => {
if (!proofs) {
notification.warning({ message: '该订单没有凭证' });
return;
}
const list = proofs.replace(/(\uff1b|\uff0c|\u003b)/g, ',').split(',');
setProofsData(list);
setProofsVisible(true);
};
// 审核
const openAudit = async ({ serviceNo, serviceType }) => {
const data = await auditInfoApi({ serviceNo });
setAuditInfo({ ...data?.data, serviceNo, serviceType });
setVisible(true);
};
// 物流拦截
const openLogistics = r => {
confirm({
title: '温馨提示',
okText: '确认拦截',
cancelText: '取消拦截',
content: (
<div>
请48小时内自行联系物流公司进行物流拦截,系统监测拦截成功后
<span className={styles.redTipBold}>自动同意</span>退款
</div>
),
async onOk() {
const data = await logisticsIntercept({ serviceNo: r.serviceNo });
if (data.businessCode === '0000') {
notification.success({ message: '拦截成功' });
actionRef.current.reload();
} else {
notification.error({ message: data.msg || '拦截失败' });
}
},
onCancel() {
console.log('Cancel');
},
});
};
// 查看
const viewDetail = async ({ serviceNo }) => {
const res = await orderDetail({ serviceNo });
const data = res.data || [];
setDetailInfo(data);
setDetailVisible(true);
};
// 查看售后操作日志
const viewLog = async r => {
const data = await getOpLog(r.serviceNo);
if (data?.data?.length) {
setAfterList(data.data);
setAfterVisible(true);
}
};
const tabChange = e => {
console.log(e);
};
const [form] = Form.useForm();
const formConfig = getFormConfig({
setTableParams,
});
const FormSearchProps = {
form,
initialValues: {},
formOptions: {},
...formConfig,
};
const columns = getColumns({
openAudit,
viewAppeal,
viewProofs,
openLogistics,
viewDetail,
viewLog,
canEditable,
});
// 表格属性
const tableProps = {
columns,
params: tableParams,
bordered: true,
scroll: { x: '100%', y: 500 },
rowKey: r => r.serviceNo,
request: async params => {
console.log(params);
console.log('搜索', params);
const { current: page, pageSize: size } = params;
const startDate = params.startDate ? moment(params.startDate).format('YYYY-MM-DD') : '';
const endDate = params.endDate ? moment(params.endDate).format('YYYY-MM-DD') : '';
const requestParams = {
page,
size,
queryStatus: 1,
...params,
startDate,
endDate,
};
const res = await searchList(requestParams);
const { records = [], total } = res.data;
return {
data: records,
total,
};
},
toolBarRender: null,
};
return (
<PageHeaderWrapper>
<FormSearch {...FormSearchProps} />
<div className={styles['tab-box']}>
<Tabs onChange={tabChange} size="large" tabBarStyle={{ padding: '0 30px' }}>
<TabPane key="" tab="全部"></TabPane>
<TabPane key={1} tab="仅退款(未发货)"></TabPane>
<TabPane key={2} tab="待审核0"></TabPane>
<TabPane key={3} tab="仅退款待审核8"></TabPane>
<TabPane key={4} tab="退货退款待审核0"></TabPane>
<TabPane key={5} tab="退货入库待审核0"></TabPane>
<TabPane key={6} tab="已完成0"></TabPane>
</Tabs>
</div>
<ProTable
{...tableProps}
actionRef={actionRef}
formRef={formRef}
search={false}
toolBarRender={false}
/>
<AuditModal visible={visible} onCancel={closeModal} formData={auditInfo} />
<DetailTable visible={detailVisible} onCancel={closeModal} dataSource={detailInfo} />
<ProofsModal visible={proofsVisible} onCancel={closeModal} data={proofsData} />
<AppealDetail
data={selectedRow}
modalVisible={appealDetailModal}
onCancel={closeModal}
></AppealDetail>
<AfterLog visible={afterVisible} onCancel={closeModal} data={afterList} />
</PageHeaderWrapper>
);
};
export default connect(({ menu }) => ({
permissions: menu.permissions,
}))(AfterSale);
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
/* eslint-disable guard-for-in */ /* eslint-disable guard-for-in */
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { Modal, Timeline, Button } from 'antd'; import { Modal, Timeline, Button } from 'antd';
import styles from '../index.less'; import styles from '../styles.less';
const LogisticsCom = props => { const LogisticsCom = props => {
const { visible, onCancel, data } = props; const { visible, onCancel, data } = props;
......
...@@ -3,7 +3,7 @@ import { Form } from '@ant-design/compatible'; ...@@ -3,7 +3,7 @@ import { Form } from '@ant-design/compatible';
import '@ant-design/compatible/assets/index.css'; import '@ant-design/compatible/assets/index.css';
import { Modal, Input, Cascader, notification, InputNumber } from 'antd'; import { Modal, Input, Cascader, notification, InputNumber } from 'antd';
import { shopAudit } from '../services'; import { shopAudit } from '../services';
import styles from '../index.less'; import styles from '../styles.less';
const FormItem = Form.Item; const FormItem = Form.Item;
const { TextArea } = Input; const { TextArea } = Input;
......
import React, { useState } from 'react'; import React, { useState } from 'react';
import { Modal } from 'antd'; import { Modal } from 'antd';
import style from '../index.less'; import style from '../styles.less';
export default props => { export default props => {
const { visible, onCancel, data } = props; const { visible, onCancel, data } = props;
......
import { Tag, Badge } from 'antd';
import React from 'react';
export const appealType = {
1: '已申诉',
0: '未申诉',
};
export const columnSticData = [
{
title: '售后类型',
dataIndex: 'serviceType',
hideInSearch: true,
width: 120,
render: serviceType => {
if (+serviceType === 1) {
return <span style={{ color: '#ff1616' }}>仅退款</span>;
}
return <span>退货退款</span>;
},
},
{
title: '订单ID',
dataIndex: 'orderNo',
hideInTable: true,
width: 200,
},
{
title: '售后单ID',
dataIndex: 'serviceNo',
width: 300,
render: (serviceNo, r) => (
<div>
{r.timeout ? <Tag color="red">{serviceNo}</Tag> : serviceNo}
{<Badge count={r.reminderFlag ? '' : ''} size="default" />}
</div>
),
},
{
title: '订单ID',
dataIndex: 'orderNo',
hideInSearch: true,
width: 300,
},
{
title: '售后状态',
dataIndex: 'dealStatus',
hideInTable: true,
valueEnum: {
0: '待审核',
10: '三方审核中',
11: '三方审核通过',
12: '三方审核拒绝',
13: '客服审核通过',
14: '商户审核中',
15: '商户审核通过',
16: '商户审核拒绝',
20: '审核拒绝',
21: '申诉中',
30: '待填写退货物流信息',
40: '待退货入库',
50: '退货拒收',
60: '待退款',
61: '退货处理中',
70: '售后成功',
99: '用户取消',
},
width: 100,
},
{
title: '售后类型',
dataIndex: 'type',
hideInTable: true,
width: 120,
valueEnum: {
1: '仅退款',
2: '退货退款',
},
},
{
title: '收货人姓名',
dataIndex: 'receiverName',
width: 200,
},
{
title: '收货人手机号',
dataIndex: 'receiverPhone',
width: 200,
},
{
title: '收货人地址',
dataIndex: 'receiveAddress',
width: 200,
hideInSearch: true,
},
{
title: '订单开始时间',
width: 120,
dataIndex: 'startDate',
key: 'startDate',
valueType: 'date',
hideInTable: true,
},
{
title: '订单结束时间',
width: 120,
dataIndex: 'endDate',
key: 'endDate',
valueType: 'date',
hideInTable: true,
},
{
title: '售后原因',
dataIndex: 'serviceReason',
hideInSearch: true,
width: 200,
},
{
title: '售后发生时间',
dataIndex: 'serviceTime',
hideInSearch: true,
width: 200,
},
{
title: '超时时间',
dataIndex: 'overtime',
hideInSearch: true,
width: 200,
},
{
title: '是否催办',
dataIndex: 'reminderFlag',
hideInSearch: true,
width: 120,
valueEnum: {
true: '',
false: '',
},
},
{
title: '是否同意售后',
dataIndex: 'isAgree',
hideInSearch: true,
width: 120,
},
{
title: '拒绝原因',
dataIndex: 'refuseReason',
hideInSearch: true,
width: 200,
},
];
export const columnPassAudit = [
...columnSticData,
{
title: '商家退货地址',
dataIndex: 'merchantAddress',
hideInSearch: true,
width: 200,
},
{
title: '退回物流',
dataIndex: 'expressCompanyName',
hideInSearch: true,
width: 150,
},
{
title: '退回物流单号',
dataIndex: 'deliveryNo',
hideInSearch: true,
width: 200,
},
{
title: '售后状态',
dataIndex: 'serviceStatus',
hideInSearch: true,
width: 120,
},
];
import { Tabs } from 'antd';
import React from 'react';
import { PageHeaderWrapper } from '@ant-design/pro-layout';
import { AFTER_SALE_ORDER } from '@/../config/permission.config';
import { connect } from 'dva';
import Pending from './Pending';
import PassAudit from './PassAudit';
const { TabPane } = Tabs;
function AfterSale(props) {
const { permissions } = props;
const canEditable = permissions[AFTER_SALE_ORDER.EDITABLE];
return (
<PageHeaderWrapper>
<Tabs defaultActiveKey="1">
<TabPane tab="未审核" key="1">
<Pending canEditable={canEditable} />
</TabPane>
<TabPane tab="已审核" key="2">
<PassAudit canEditable={canEditable} />
</TabPane>
</Tabs>
</PageHeaderWrapper>
);
}
export default connect(({ menu }) => ({
permissions: menu.permissions,
}))(AfterSale);
...@@ -6,40 +6,31 @@ import _ from 'lodash'; ...@@ -6,40 +6,31 @@ import _ from 'lodash';
const { kdspApi } = config; const { kdspApi } = config;
// 分页查询所有数据 // 分页查询所有数据
export const searchList = params => export async function searchList(params, queryStatus) {
request.post('/api/kdsp/op/afs/shop/list', { const param = {
...params,
pageNo: params.current,
pageSize: params.pageSize || 20,
queryStatus,
};
const data = await request.post('/api/kdsp/op/afs/shop/list', {
prefix: kdspApi, prefix: kdspApi,
data: stringify(_.omitBy(params, v => !v)), data: stringify(_.omitBy(param, v => !v)),
headers: { headers: {
'Content-Type': 'application/x-www-form-urlencoded', 'Content-Type': 'application/x-www-form-urlencoded',
}, },
}); });
if (data.data) {
// export async function searchList(params, queryStatus) { return {
// const param = { total: data.data.total,
// ...params, data: data.data.records,
// pageNo: params.current, };
// pageSize: params.pageSize || 20, }
// queryStatus, return {
// }; total: 0,
// const data = await request.post('/api/kdsp/op/afs/shop/list', { data: [],
// prefix: kdspApi, };
// data: stringify(_.omitBy(param, v => !v)), }
// headers: {
// 'Content-Type': 'application/x-www-form-urlencoded',
// },
// });
// if (data.data) {
// return {
// total: data.data.total,
// data: data.data.records,
// };
// }
// return {
// total: 0,
// data: [],
// };
// }
// 售后单详情 // 售后单详情
export async function orderDetail(params) { export async function orderDetail(params) {
......
import request from '@/utils/request'; import request from '@/utils/request';
import config from '../../config/env.config'; import config from '../../config/env.config';
const { msgApi } = config; const { msgApi, wsApi } = config;
export const getSocketUrl = ({ token, channelId }) =>
`${wsApi}/ws?token=${token}&channelId=${channelId}`;
/** /**
* @name 商户消息列表 * @name 商户消息列表
* @see http://yapi.quantgroups.com/project/193/interface/api/41792 * @see http://yapi.quantgroups.com/project/193/interface/api/41792
...@@ -21,9 +25,6 @@ export function apiGetBussinessMsgList(data, params) { ...@@ -21,9 +25,6 @@ export function apiGetBussinessMsgList(data, params) {
export function apiGetBusinessMsgUnReadCount(data) { export function apiGetBusinessMsgUnReadCount(data) {
return request.post('/v1/send/message/getBusinessMsgUnReadCount', { return request.post('/v1/send/message/getBusinessMsgUnReadCount', {
data, data,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
prefix: msgApi, prefix: msgApi,
}); });
} }
......
...@@ -76,13 +76,16 @@ class Socket extends EventEmitter { ...@@ -76,13 +76,16 @@ class Socket extends EventEmitter {
if (e.code === '4500') { if (e.code === '4500') {
this.socket.close(); this.socket.close();
} else { } else {
this.taskRemindInterval = setInterval(() => { const reconnect = () => {
if (!this.connected) { clearTimeout(this.taskRemindInterval);
this.connection(); this.taskRemindInterval = setTimeout(() => {
} else { if (!this.connected) {
clearInterval(this.taskRemindInterval); this.connection();
} reconnect();
}, 2000); }
}, 5000);
};
reconnect();
} }
}; };
......
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