Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
M
merchant-manage-ui
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
ui
merchant-manage-ui
Commits
42a1a428
Commit
42a1a428
authored
Jan 09, 2024
by
guang.wu
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix: 去掉订单消息模块
parent
6c3c8269
Changes
13
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
4 additions
and
1285 deletions
+4
-1285
MessageIcon.jsx
src/components/GlobalHeader/MessageIcon.jsx
+0
-33
RightContent.jsx
src/components/GlobalHeader/RightContent.jsx
+1
-4
index.jsx
src/components/MessageReminder/Complex/index.jsx
+0
-347
index.less
src/components/MessageReminder/Complex/index.less
+0
-154
index.jsx
src/components/MessageReminder/Empty/index.jsx
+0
-17
index.less
src/components/MessageReminder/Empty/index.less
+0
-12
index.jsx
src/components/MessageReminder/Simple/index.jsx
+0
-270
index.less
src/components/MessageReminder/Simple/index.less
+0
-199
index.jsx
src/components/MessageReminder/index.jsx
+0
-9
BasicLayout.jsx
src/layouts/BasicLayout.jsx
+2
-27
messageReminder.js
src/models/messageReminder.js
+0
-65
messageReminder.js
src/services/messageReminder.js
+1
-4
websocket.js
src/utils/websocket.js
+0
-144
No files found.
src/components/GlobalHeader/MessageIcon.jsx
deleted
100644 → 0
View file @
6c3c8269
import
React
,
{
useState
,
useEffect
}
from
'
react
'
;
import
{
Tag
,
message
,
Badge
}
from
'
antd
'
;
import
{
connect
}
from
'
dva
'
;
import
groupBy
from
'
lodash/groupBy
'
;
import
moment
from
'
moment
'
;
import
{
BellOutlined
}
from
'
@ant-design/icons
'
;
import
NoticeIcon
from
'
../NoticeIcon
'
;
import
styles
from
'
./index.less
'
;
const
GlobalHeaderRight
=
props
=>
{
const
{
messageReminderComplexRef
,
unReadCount
=
0
}
=
props
;
const
[
count
,
setCount
]
=
useState
(
0
);
const
open
=
()
=>
{
messageReminderComplexRef
.
current
.
open
();
};
useEffect
(()
=>
{
setCount
(
unReadCount
);
},
[
unReadCount
]);
return
(
<
span
className=
{
styles
[
'
badge-box
'
]
}
onClick=
{
open
}
>
<
Badge
count=
{
count
}
className=
{
styles
[
'
badge-box__self
'
]
}
>
<
BellOutlined
className=
{
styles
[
'
badge-box__icon
'
]
}
/>
</
Badge
>
</
span
>
);
};
export
default
connect
(({
messageReminder
})
=>
({
unReadCount
:
messageReminder
.
unReadCount
,
}))(
GlobalHeaderRight
);
src/components/GlobalHeader/RightContent.jsx
View file @
42a1a428
import
{
Tooltip
}
from
'
antd
'
;
import
React
from
'
react
'
;
import
{
NotificationOutlined
}
from
'
@ant-design/icons
'
;
import
{
connect
}
from
'
dva
'
;
import
Avatar
from
'
./AvatarDropdown
'
;
import
HeaderSearch
from
'
../HeaderSearch
'
;
import
styles
from
'
./index.less
'
;
import
MessageIcon
from
'
./MessageIcon
'
;
const
GlobalHeaderRight
=
props
=>
{
const
{
theme
,
layout
,
messageReminderComplexRef
}
=
props
;
const
{
theme
,
layout
}
=
props
;
let
className
=
styles
.
right
;
if
(
theme
===
'
dark
'
&&
layout
===
'
topmenu
'
)
{
...
...
@@ -17,7 +15,6 @@ const GlobalHeaderRight = props => {
return
(
<
div
className=
{
className
}
>
<
MessageIcon
messageReminderComplexRef=
{
messageReminderComplexRef
}
/>
<
Avatar
/>
</
div
>
);
...
...
src/components/MessageReminder/Complex/index.jsx
deleted
100644 → 0
View file @
6c3c8269
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
{
apiGetBussinessMsgList
,
apiGetBusinessMsgUnReadCount
}
from
'
@/services/messageReminder
'
;
import
{
connect
}
from
'
dva
'
;
import
Empty
from
'
../Empty
'
;
import
styles
from
'
./index.less
'
;
import
{
CHANNEL_ID
}
from
'
@/utils/constants
'
;
const
INIT_PAGINATION
=
{
pageSize
:
20
,
pageNo
:
1
,
};
const
INIT_QUERY_PARAMS
=
{
type
:
'
0
'
,
readStatus
:
''
,
};
const
MessageItem
=
props
=>
{
const
{
item
,
onMark
,
viewDetail
}
=
props
;
/**
* type: 0订单消息,1售后消息
* readStatus: 0未读,1已读
*/
const
{
readStatus
,
type
}
=
item
;
let
message
=
{};
try
{
message
=
JSON
.
parse
(
item
.
sendContent
||
'
{}
'
);
}
catch
(
e
)
{
console
.
error
(
'
消息数据格式错误
'
);
}
const
goodList
=
message
.
items
.
map
((
good
,
index
)
=>
(
<
div
className=
{
styles
.
good
}
key=
{
String
(
index
)
}
>
<
span
className=
{
styles
.
good__name
}
>
{
good
.
skuName
}
</
span
>
<
span
className=
{
styles
.
good__count
}
>
x
{
good
.
quantity
}
</
span
>
</
div
>
));
return
(
<
div
className=
{
styles
[
'
complex-list__item
'
]
}
>
<
div
className=
{
styles
[
'
complex-list__item--header
'
]
}
>
<
span
className=
{
styles
[
'
order-number
'
]
}
>
订单编号:
{
message
.
orderNo
}
</
span
>
<
span
className=
{
styles
.
time
}
>
订单时间:
{
message
.
time
}
</
span
>
<
span
className=
{
styles
[
'
read-status
'
]
}
>
{
readStatus
===
0
?
(
<
a
className=
{
styles
[
'
read-status--un-read
'
]
}
onClick=
{
()
=>
onMark
([
item
.
id
])
}
>
标记为已读
</
a
>
)
:
(
<
span
className=
{
styles
[
'
read-status--read
'
]
}
>
已读
</
span
>
)
}
</
span
>
</
div
>
<
div
className=
{
styles
[
'
complex-list__item--body
'
]
}
>
{
goodList
}
</
div
>
<
div
className=
{
styles
[
'
complex-list__item--footer
'
]
}
>
<
div
className=
{
styles
.
actions
}
>
<
a
onClick=
{
()
=>
viewDetail
(
message
)
}
className=
{
[
styles
.
notice
,
readStatus
===
0
?
styles
[
'
un-read
'
]
:
''
].
join
(
'
'
)
}
>
{
message
.
title
}
,请查看
</
a
>
</
div
>
</
div
>
</
div
>
);
};
const
Complex
=
props
=>
{
const
{
dispatch
,
refInstance
}
=
props
;
const
history
=
useHistory
();
const
[
visible
,
setVisible
]
=
useState
(
false
);
const
[
dataTotal
,
setDataTotal
]
=
useState
(
10
);
const
[
loading
,
setLoading
]
=
useState
(
false
);
// 消息列表数据
const
[
messageData
,
setMessageData
]
=
useState
([]);
// 未读消息
const
[
orderUnReadCount
,
setOrderUnReadCount
]
=
useState
(
0
);
const
[
afterUnReadCount
,
setAfterUnReadCount
]
=
useState
(
0
);
// 消息列表参数
const
[
queryParams
,
setQueryParams
]
=
useState
({
...
INIT_QUERY_PARAMS
,
...
INIT_PAGINATION
});
const
userInfo
=
JSON
.
parse
(
localStorage
.
getItem
(
'
user
'
)
||
'
{}
'
);
// 获取信息列表
const
getMsgList
=
async
()
=>
{
const
params
=
{
pageSize
:
queryParams
.
pageSize
,
pageNo
:
queryParams
.
pageNo
,
};
const
data
=
{
channelId
:
CHANNEL_ID
,
bussinessId
:
userInfo
.
supplierCode
,
...
queryParams
,
};
delete
data
.
pageSize
;
delete
data
.
pageNo
;
setLoading
(
true
);
const
res
=
await
apiGetBussinessMsgList
(
data
,
params
);
setLoading
(
false
);
if
(
!
res
)
return
;
if
(
res
.
code
!==
'
0000
'
)
{
notification
.
error
(
res
.
msg
);
return
;
}
const
{
content
,
totalElements
}
=
res
.
data
;
setMessageData
(
content
);
setDataTotal
(
totalElements
);
};
// 获取未读数量
const
getMsgReadCount
=
async
()
=>
{
const
data
=
{
channelId
:
CHANNEL_ID
,
bussinessId
:
userInfo
.
supplierCode
,
};
const
res
=
await
apiGetBusinessMsgUnReadCount
(
data
);
if
(
res
.
code
!==
'
0000
'
)
{
notification
.
error
(
res
.
msg
);
return
;
}
const
{
afterSalesUnRead
,
orderUnRead
}
=
res
.
data
;
setOrderUnReadCount
(
orderUnRead
);
setAfterUnReadCount
(
afterSalesUnRead
);
};
// 分页操作
const
onPageChange
=
(
page
,
size
)
=>
{
const
current
=
queryParams
.
pageSize
!==
size
?
1
:
page
;
setQueryParams
({
...
queryParams
,
pageNo
:
current
,
pageSize
:
size
,
});
};
// 筛选未读/已读
const
onReadStatusChange
=
e
=>
{
let
{
value
}
=
e
.
target
;
if
(
queryParams
.
readStatus
===
e
.
target
.
value
)
{
value
=
''
;
}
setQueryParams
({
...
queryParams
,
readStatus
:
value
,
});
};
// 过滤参数,获取当前页未读消息数据的id
const
onFilterMessageParams
=
msgList
=>
msgList
.
filter
(
message
=>
message
.
readStatus
===
0
).
map
(
item
=>
item
.
id
);
const
open
=
()
=>
{
setVisible
(
true
);
getMsgReadCount
();
};
const
close
=
()
=>
{
setMessageData
([]);
setVisible
(
false
);
};
//
/**
* 跳转到详情
* type
* 1-待发货订单
* 2-超时发货
* 3-仅退款(未发货)申请单
* 4-仅退款申请单
* 5-退货退款申请单
* 6-退货入库待审核
*/
const
viewDetail
=
message
=>
{
const
{
orderNo
,
type
}
=
message
;
if
([
1
,
2
].
includes
(
type
))
{
history
.
push
({
pathname
:
'
/orderManage/pendingDeliveryOrder
'
,
query
:
{
orderNo
},
});
}
if
([
3
,
4
,
5
,
6
].
includes
(
type
))
{
history
.
push
({
pathname
:
'
/afterSaleManage
'
,
query
:
{
orderNo
},
});
}
close
();
};
// 切换消息类型
const
onTabChange
=
index
=>
{
setQueryParams
({
...
queryParams
,
...
INIT_PAGINATION
,
type
:
index
,
});
};
// 标记已读
const
onMark
=
idsList
=>
{
if
(
!
idsList
.
length
)
{
return
;
}
const
payload
=
{
channelId
:
CHANNEL_ID
,
bussinessId
:
userInfo
.
supplierCode
,
type
:
Number
(
queryParams
.
type
),
idsList
,
};
dispatch
({
type
:
'
messageReminder/setMarkRead
'
,
payload
,
options
:
{
setLoading
,
callback
:
()
=>
{
getMsgReadCount
();
getMsgList
();
},
},
});
};
// 展开初始化
useEffect
(()
=>
{
if
(
visible
)
{
getMsgList
();
}
},
[
visible
,
queryParams
]);
useEffect
(()
=>
{
if
(
!
visible
)
{
setQueryParams
({
...
INIT_QUERY_PARAMS
,
...
INIT_PAGINATION
});
}
},
[
visible
]);
useImperativeHandle
(
refInstance
,
()
=>
({
open
,
}));
const
modalProps
=
{
bodyStyle
:
{
display
:
'
flex
'
,
flexWrap
:
'
wrap
'
,
padding
:
0
,
backgroundColor
:
'
#f7f8f9
'
,
},
wrapClassName
:
'
complex-modal
'
,
width
:
'
880px
'
,
height
:
'
650px
'
,
visible
,
title
:
<
span
className=
"title-icon"
>
消息提醒
</
span
>,
footer
:
null
,
onCancel
:
close
,
};
const
TabRender
=
tabProps
=>
{
const
{
title
,
count
=
0
}
=
tabProps
;
return
(
<
span
className=
{
styles
[
'
tab-render
'
]
}
>
{
title
}
<
Badge
overflowCount=
{
999
}
count=
{
count
}
/>
</
span
>
);
};
const
FilterRender
=
filterProps
=>
(
<
div
className=
{
styles
[
'
filter-box
'
]
}
>
<
div
className=
{
styles
[
'
filter-box__content
'
]
}
>
<
Checkbox
checked=
{
queryParams
.
readStatus
===
'
0
'
}
value=
"0"
onChange=
{
onReadStatusChange
}
>
未读
</
Checkbox
>
<
Checkbox
checked=
{
queryParams
.
readStatus
===
'
1
'
}
value=
"1"
onChange=
{
onReadStatusChange
}
>
已读
</
Checkbox
>
</
div
>
<
div
className=
{
styles
[
'
filter-box__actions
'
]
}
>
<
a
onClick=
{
()
=>
onMark
(
onFilterMessageParams
(
messageData
))
}
>
全部标记为已读
</
a
>
</
div
>
</
div
>
);
return
(
<
Modal
{
...
modalProps
}
>
<
Tabs
className=
{
styles
.
tabs
}
activeKey=
{
queryParams
.
type
}
tabBarStyle=
{
{
width
:
'
150px
'
,
}
}
tabPosition=
"left"
tabBarGutter=
{
0
}
onChange=
{
onTabChange
}
>
<
Tabs
.
TabPane
tab=
{
<
TabRender
title=
"订单消息"
count=
{
orderUnReadCount
}
/>
}
key=
"0"
/>
<
Tabs
.
TabPane
tab=
{
<
TabRender
title=
"售后消息"
count=
{
afterUnReadCount
}
/>
}
key=
"1"
/>
</
Tabs
>
<
div
className=
{
styles
[
'
tab-pane
'
]
}
>
<
Spin
spinning=
{
loading
}
>
<
FilterRender
/>
<
div
className=
{
styles
[
'
complex-list
'
]
}
>
{
visible
&&
messageData
.
length
?
(
messageData
.
map
((
item
,
index
)
=>
(
<
MessageItem
key=
{
String
(
index
)
}
item=
{
item
}
onMark=
{
onMark
}
viewDetail=
{
viewDetail
}
/>
))
)
:
(
<
Empty
text=
"暂无数据"
/>
)
}
</
div
>
</
Spin
>
{
dataTotal
>
0
?
(
<
div
className=
{
styles
.
pagination
}
>
<
Pagination
onChange=
{
onPageChange
}
total=
{
dataTotal
}
showTotal=
{
(
total
,
range
)
=>
`第${range[0]}-${range[1]}条 /总共${total}条`
}
showSizeChanger
pageSize=
{
queryParams
.
pageSize
}
current=
{
queryParams
.
pageNo
}
/>
</
div
>
)
:
(
''
)
}
</
div
>
</
Modal
>
);
};
const
MiddleComponent
=
connect
(({
messageReminder
})
=>
({
unReadCount
:
messageReminder
.
unReadCount
,
unReadData
:
messageReminder
.
unReadData
,
}))(
Complex
);
// 注意:这里不要在Component上使用ref;换个属性名字比如refInstance;不然会导致覆盖
export
default
forwardRef
((
props
,
ref
)
=>
<
MiddleComponent
{
...
props
}
refInstance=
{
ref
}
/>);
src/components/MessageReminder/Complex/index.less
deleted
100644 → 0
View file @
6c3c8269
.tab-pane {
flex: 1;
}
.tabs {
:global .ant-tabs-tab {
height: 48px;
line-height: 48px;
border-bottom: 1px solid #efefef;
}
:global .ant-tabs-ink-bar {
height: 40px !important;
margin-top: 4px !important;
}
}
.tab-render {
display: flex;
align-items: center;
:global .ant-badge {
margin-left: 5px;
}
}
.filter-box {
display: flex;
margin-top: 15px;
padding-right: 25px;
&__content {
flex: 1;
}
}
:global .complex-modal {
.ant-modal-header {
text-align: center;
background-color: #2d8cf0;
}
.ant-modal-title,
.ant-modal-close {
color: #fff;
.title-icon {
padding-left: 25px;
background: #1890ff url('https://img.op5po.net/notice.94d42513.png') no-repeat 0 center;
background-size: 20px 20px;
}
}
}
.complex-list {
min-height: 300px;
max-height: 500px;
margin-top: 20px;
padding-right: 25px;
overflow-y: auto;
& :first-child {
margin: 0;
}
&__item {
margin-top: 15px;
background: #fff;
border: 1px solid #efefef;
&--header {
display: flex;
width: 100%;
height: 40px;
padding: 0 15px;
line-height: 40px;
background: #fff;
border-bottom: 1px solid #efefef;
.order-number,
.time {
flex: 1;
padding-right: 20px;
color: #999;
word-break: break-all;
// white-space: nowrap
}
.read-status {
min-width: 80px;
text-align: right;
&--read {
color: #999;
}
}
}
&--body {
padding: 10px 15px;
.good {
display: flex;
padding: 5px 0;
line-height: 1.5;
&__name {
flex: 1;
word-break: break-all;
}
&__count {
min-width: 80px;
text-align: right;
}
}
}
&--footer {
display: flex;
border-top: 1px solid #efefef;
.actions {
display: flex;
width: 100%;
margin-left: 20px;
line-height: 40px;
.notice {
position: relative;
display: block;
flex: 1;
color: #999;
font-weight: 400;
&.un-read {
color: #ff1515;
&::before {
display: inline-block;
width: 6px;
height: 6px;
margin-top: 17px;
margin-right: 6px;
vertical-align: top;
background: #ff1515;
border-radius: 50%;
content: '';
}
}
&::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: '';
}
}
}
}
}
}
.pagination {
width: 100%;
padding: 25px;
text-align: right;
}
src/components/MessageReminder/Empty/index.jsx
deleted
100644 → 0
View file @
6c3c8269
import
React
from
'
react
'
;
import
styles
from
'
./index.less
'
;
const
MessageReminderEmpty
=
props
=>
{
const
{
text
}
=
props
;
return
(
<
div
className=
{
styles
.
notFound
}
>
<
img
src=
"https://gw.alipayobjects.com/zos/rmsportal/sAuJeJzSKbUmHfBQRzmZ.svg"
alt=
"not found"
/>
<
div
>
{
text
}
</
div
>
</
div
>
);
};
export
default
MessageReminderEmpty
;
src/components/MessageReminder/Empty/index.less
deleted
100644 → 0
View file @
6c3c8269
@import '~antd/es/style/themes/default.less';
.notFound {
padding: 73px 0 88px;
color: @text-color-secondary;
text-align: center;
background-color: #fff;
img {
display: inline-block;
height: 76px;
margin-bottom: 16px;
}
}
src/components/MessageReminder/Simple/index.jsx
deleted
100644 → 0
View file @
6c3c8269
import
React
,
{
useState
,
useEffect
}
from
'
react
'
;
import
{
Badge
,
notification
,
Spin
}
from
'
antd
'
;
import
{
CloseOutlined
,
DoubleLeftOutlined
,
DoubleRightOutlined
}
from
'
@ant-design/icons
'
;
import
classNames
from
'
classnames
'
;
import
{
useHistory
}
from
'
react-router-dom
'
;
// import copy from 'copy-to-clipboard';
import
{
connect
}
from
'
dva
'
;
import
{
apiGetBussinessMsgList
}
from
'
@/services/messageReminder
'
;
import
Empty
from
'
../Empty
'
;
import
styles
from
'
./index.less
'
;
import
{
CHANNEL_ID
}
from
'
@/utils/constants
'
;
const
Horn
=
props
=>
{
const
{
count
,
toggle
,
animationClass
,
stowClass
,
onStow
}
=
props
;
return
(
<
div
className=
{
classNames
(
styles
.
horn
,
styles
[
animationClass
],
styles
[
stowClass
])
}
onClick=
{
toggle
}
>
<
span
className=
{
styles
[
'
horn--btn
'
]
}
onClick=
{
e
=>
onStow
(
e
)
}
>
{
stowClass
?
<
DoubleLeftOutlined
/>
:
<
DoubleRightOutlined
/>
}
</
span
>
<
Badge
count=
{
count
}
>
<
div
className=
{
styles
[
'
horn--num
'
]
}
>
消息提醒
</
div
>
</
Badge
>
</
div
>
);
};
const
Message
=
props
=>
{
const
{
toggle
,
animationClass
,
messageData
,
openComplex
,
onMark
,
loading
,
viewDetail
,
onStow
,
stowClass
,
}
=
props
;
const
ReminderItem
=
args
=>
{
const
{
item
}
=
args
;
let
message
=
{};
try
{
message
=
JSON
.
parse
(
item
.
sendContent
||
'
{}
'
);
}
catch
(
e
)
{
console
.
error
(
'
消息数据格式错误
'
);
}
return
(
<
div
className=
{
styles
.
item
}
>
<
div
className=
{
styles
.
info
}
>
<
span
className=
{
styles
[
'
order-number
'
]
}
>
{
message
.
orderNo
}
</
span
>
<
span
className=
{
styles
[
'
mark-read
'
]
}
onClick=
{
()
=>
onMark
([
item
.
id
])
}
>
标记为已读
</
span
>
</
div
>
<
div
className=
{
styles
.
time
}
>
<
span
>
{
message
.
time
}
</
span
>
</
div
>
<
div
className=
{
styles
.
notice
}
>
<
a
onClick=
{
()
=>
viewDetail
(
message
)
}
>
{
message
.
title
}
,请查看
</
a
>
</
div
>
</
div
>
);
};
return
(
<
div
className=
{
classNames
(
styles
[
'
message-reminder
'
],
styles
[
animationClass
])
}
>
<
div
className=
{
styles
[
'
message-reminder__header
'
]
}
>
<
div
className=
{
styles
[
'
message-reminder__header--title
'
]
}
>
消息提醒
<
span
className=
{
styles
.
close
}
onClick=
{
toggle
}
>
<
CloseOutlined
/>
</
span
>
</
div
>
</
div
>
<
div
className=
{
styles
[
'
message-reminder__body
'
]
}
>
<
Spin
spinning=
{
loading
}
>
<
div
className=
{
styles
[
'
message-reminder__body--list
'
]
}
>
{
messageData
.
length
?
(
messageData
.
filter
((
e
,
i
)
=>
i
<
10
)
.
map
(
item
=>
<
ReminderItem
key=
{
item
.
id
}
item=
{
item
}
/>)
)
:
(
<
Empty
text=
"暂无数据"
/>
)
}
</
div
>
</
Spin
>
</
div
>
<
div
className=
{
styles
[
'
message-reminder__footer
'
]
}
>
<
div
className=
{
styles
[
'
message-reminder__footer--actions
'
]
}
>
<
div
className=
{
styles
.
more
}
onClick=
{
openComplex
}
>
查看更多
</
div
>
<
div
className=
{
styles
[
'
mark-all
'
]
}
onClick=
{
()
=>
{
onMark
(
messageData
.
filter
((
e
,
i
)
=>
i
<
10
).
map
(
item
=>
item
.
id
));
}
}
>
全部标记为已读
</
div
>
</
div
>
</
div
>
</
div
>
);
};
const
Simple
=
props
=>
{
const
{
dispatch
,
unReadCount
,
complexRef
,
unReadData
}
=
props
;
const
history
=
useHistory
();
const
[
visible
,
setVisible
]
=
useState
(
false
);
const
[
loading
,
setLoading
]
=
useState
(
false
);
const
[
count
,
setCount
]
=
useState
(
0
);
const
[
hornClass
,
setHornClass
]
=
useState
(
''
);
const
[
messageClass
,
setMessageClass
]
=
useState
(
''
);
const
[
stowClass
,
setStowClass
]
=
useState
(
''
);
const
[
messageData
,
setMessageData
]
=
useState
([]);
let
userInfo
=
JSON
.
parse
(
localStorage
.
getItem
(
'
user
'
)
||
'
{}
'
);
const
toggle
=
()
=>
{
setVisible
(
!
visible
);
};
// 初始化获取数据
const
getMsgList
=
async
()
=>
{
if
(
!
userInfo
.
supplierCode
)
{
userInfo
=
JSON
.
parse
(
localStorage
.
getItem
(
'
user
'
)
||
'
{}
'
);
setTimeout
(()
=>
{
getMsgList
();
},
1000
);
return
;
}
const
params
=
{
pageNo
:
1
,
pageSize
:
200
,
};
const
data
=
{
channelId
:
CHANNEL_ID
,
bussinessId
:
userInfo
.
supplierCode
,
readStatus
:
0
,
};
setLoading
(
true
);
const
res
=
await
apiGetBussinessMsgList
(
data
,
params
);
setLoading
(
false
);
if
(
!
res
)
return
;
if
(
res
.
code
!==
'
0000
'
)
{
notification
.
error
(
res
.
msg
);
return
;
}
const
{
content
}
=
res
.
data
;
setVisible
(
!!
content
.
length
);
dispatch
({
type
:
'
messageReminder/setUnReadData
'
,
payload
:
content
,
options
:
{
unReadCount
:
content
.
length
,
},
});
};
const
viewDetail
=
message
=>
{
const
{
orderNo
,
type
}
=
message
;
console
.
log
(
type
);
if
([
1
,
2
].
includes
(
type
))
{
history
.
push
({
pathname
:
'
/orderManage/pendingDeliveryOrder
'
,
query
:
{
orderNo
},
});
}
if
([
3
,
4
,
5
,
6
].
includes
(
type
))
{
history
.
push
({
pathname
:
'
/afterSaleManage
'
,
query
:
{
orderNo
},
});
}
toggle
();
};
// 打开消息提醒弹框
const
openComplex
=
()
=>
{
complexRef
.
current
.
open
();
toggle
();
};
const
onStow
=
e
=>
{
e
.
preventDefault
();
e
.
stopPropagation
();
if
(
stowClass
)
{
setStowClass
(
''
);
}
else
{
setStowClass
(
'
stow
'
);
}
};
// 标记已读信息
const
onMark
=
idsList
=>
{
if
(
!
idsList
.
length
)
{
return
;
}
const
payload
=
{
channelId
:
CHANNEL_ID
,
bussinessId
:
userInfo
.
supplierCode
,
idsList
,
};
dispatch
({
type
:
'
messageReminder/setMarkRead
'
,
payload
,
options
:
{
setLoading
,
},
});
};
useEffect
(()
=>
{
setCount
(
unReadCount
);
},
[
unReadCount
]);
useEffect
(()
=>
{
setHornClass
(
visible
?
'
hide
'
:
'
show
'
);
setMessageClass
(
visible
?
'
show
'
:
'
hide
'
);
},
[
visible
]);
useEffect
(()
=>
{
getMsgList
();
},
[]);
useEffect
(()
=>
{
setMessageData
(
unReadData
);
},
[
unReadData
]);
const
hornProps
=
{
animationClass
:
hornClass
,
stowClass
,
toggle
,
count
,
onStow
,
};
const
messageProps
=
{
animationClass
:
messageClass
,
toggle
,
messageData
,
openComplex
,
onMark
,
loading
,
viewDetail
,
};
// 隐藏消息提醒
return
(
<>
<
Horn
{
...
hornProps
}
/>
<
Message
{
...
messageProps
}
/>
</>
);
};
export
default
connect
(({
messageReminder
})
=>
({
unReadCount
:
messageReminder
.
unReadCount
,
unReadData
:
messageReminder
.
unReadData
,
}))(
Simple
);
src/components/MessageReminder/Simple/index.less
deleted
100644 → 0
View file @
6c3c8269
.horn {
position: fixed;
right: 30px;
bottom: 10px;
z-index: 19;
// width: 112px;
// height: 50px;
color: #fff;
background: #2d8cf0;
transform: translate(0, 0);
cursor: pointer;
opacity: 1;
transition: 0.2s ease-in;
&.hide {
transform: translateY(100%) scale(0.3);
opacity: 0;
transition: 0.2s ease-out;
}
&.stow {
transform: translateX(142px);
transition: 0.2s ease-out;
}
&--btn {
display: inline-block;
width: 20px;
height: 50px;
line-height: 50px;
text-align: center;
vertical-align: top;
background: #006ad9;
border-right: 1px solid #2479d3;
&:hover {
background: #2479d3;
transition: 0.2s ease-out;
}
}
&--num {
width: 112px;
height: 50px;
color: #fff;
font-size: 16px;
line-height: 50px;
text-align: center;
&::before {
display: inline-block;
width: 20px;
height: 20px;
margin-right: 5px;
vertical-align: -3px;
background: url('https://img.op5po.net/notice.94d42513.png') no-repeat;
background-size: 100% 100%;
content: '';
}
}
}
.message-reminder {
position: fixed;
right: 10px;
bottom: 10px;
z-index: 19;
display: flex;
flex-direction: column;
width: 404px;
height: 412px;
background: #fff;
transform: translate(50%, 110%) scale(0.5);
transition: 0.2s ease-in;
&.hide {
transform: translate(50%, 110%) scale(0.5);
opacity: 0;
transition: 0.2s ease-out;
}
&.show {
transform: translateY(0) scale(1);
opacity: 1;
transition: 0.2s ease-in;
}
&__header {
&--title {
position: relative;
padding-left: 35px;
color: #fff;
font-weight: 700;
font-size: 16px;
line-height: 50px;
background: #1890ff url('https://img.op5po.net/notice.94d42513.png') no-repeat 10px center;
background-size: 20px 20px;
.close {
position: absolute;
right: 20px;
font-weight: 400;
cursor: pointer;
}
}
}
&__body {
flex: 1;
padding: 15px;
overflow: auto;
background: #f8f8f9;
&--list {
& .item:first-child {
margin-top: 0;
}
.item {
margin-top: 15px;
padding: 15px 0;
background: #fff;
border: 1px solid #efefef;
&:hover {
// border-color: #ccc;
// transition: 0.2s linear;
}
}
.info {
display: flex;
padding: 0 15px;
.order-number {
flex: 1;
padding-left: 20px;
background: url('https://img.op5po.net/order_no.f4e0a8b3.png') no-repeat scroll 0 center;
}
.mark-read {
color: #178fff;
cursor: pointer;
}
}
.time {
display: flex;
margin-top: 12px;
padding: 0 15px;
span {
flex: 1;
padding-left: 20px;
background: url('https://img.op5po.net/datetime.1b5f9199.png') no-repeat scroll 0 center;
}
}
.notice {
margin-top: 12px;
padding: 10px 15px 0;
border-top: 1px solid #efefef;
a {
position: relative;
display: block;
color: #ff1515;
&::before {
display: inline-block;
width: 6px;
height: 6px;
margin-top: 8px;
margin-right: 6px;
vertical-align: top;
background: #ff1515;
border-radius: 50%;
content: '';
}
&::after {
position: absolute;
top: 50%;
right: 0;
display: block;
width: 0;
height: 0;
margin-top: -3px;
border: 6px solid transparent;
border-left: 8px solid #999;
content: '';
}
}
}
}
}
&__footer {
background-color: #fff;
border: 1px solid #efefef;
&--actions {
display: flex;
& div:first-child {
border: none;
}
> div {
flex: 1;
color: #2d8cf0;
line-height: 40px;
text-align: center;
border-left: 1px solid #efefef;
cursor: pointer;
// &:hover {
// background: #f9f9f9;
// cursor: pointer;
// }
}
}
}
}
src/components/MessageReminder/index.jsx
deleted
100644 → 0
View file @
6c3c8269
import
Simple
from
'
./Simple
'
;
import
Complex
from
'
./Complex
'
;
const
MessageReminder
=
{};
MessageReminder
.
Simple
=
Simple
;
MessageReminder
.
Complex
=
Complex
;
export
default
MessageReminder
;
src/layouts/BasicLayout.jsx
View file @
42a1a428
...
...
@@ -12,15 +12,11 @@ import { Icon as LegacyIcon } from '@ant-design/compatible';
import
{
Result
,
Button
,
Layout
,
Menu
}
from
'
antd
'
;
import
Authorized
from
'
@/utils/Authorized
'
;
import
RightContent
from
'
@/components/GlobalHeader/RightContent
'
;
import
MessageReminder
from
'
@/components/MessageReminder
'
;
import
{
getAuthorityFromRouter
,
getUrlSearchParams
,
getToken
}
from
'
@/utils/utils
'
;
import
{
getSocketUrl
}
from
'
@/services/messageReminder
'
;
import
logo
from
'
../assets/logo.png
'
;
import
style
from
'
./BasicLayout.less
'
;
import
Socket
from
'
@/utils/websocket
'
;
import
{
CHANNEL_ID
}
from
'
@/utils/constants
'
;
const
{
Sider
}
=
Layout
;
const
{
SubMenu
}
=
Menu
;
...
...
@@ -53,24 +49,12 @@ const BasicLayout = props => {
}
=
props
;
const
[
siderCollapsed
,
setSiderCollapsed
]
=
useState
(
false
);
const
messageReminderComplexRef
=
useRef
();
// const audioRef = useRef()
useEffect
(()
=>
{
try
{
const
token
=
getToken
();
const
socket
=
new
Socket
({
url
:
getSocketUrl
({
token
,
channelId
:
CHANNEL_ID
}),
});
socket
.
connection
();
socket
.
event
.
on
(
'
message
'
,
msg
=>
{
dispatch
({
type
:
'
messageReminder/setUnReadData
'
,
payload
:
[
JSON
.
parse
(
msg
.
data
)],
});
});
}
catch
(
e
)
{
console
.
log
(
e
);
}
...
...
@@ -82,9 +66,6 @@ const BasicLayout = props => {
dispatch
({
type
:
'
menu/getMenuData
'
,
});
dispatch
({
type
:
'
messageReminder/getUnReadMsgList
'
,
});
}
},
[]);
/**
...
...
@@ -184,9 +165,7 @@ const BasicLayout = props => {
);
}
}
menuDataRender=
{
()
=>
menuData
}
rightContentRender=
{
rightProps
=>
(
<
RightContent
{
...
rightProps
}
messageReminderComplexRef=
{
messageReminderComplexRef
}
/>
)
}
rightContentRender=
{
rightProps
=>
<
RightContent
{
...
rightProps
}
/>
}
pageTitleRender=
{
()
=>
''
}
menuHeaderRender=
{
()
=>
(
<
div
className=
{
style
[
'
custom-title-box
'
]
}
onClick=
{
toIndex
}
>
...
...
@@ -199,10 +178,6 @@ const BasicLayout = props => {
<
Authorized
authority=
{
authorized
.
authority
}
noMatch=
{
noMatch
}
>
{
children
}
</
Authorized
>
<
MessageReminder
.
Simple
complexRef=
{
messageReminderComplexRef
}
/>
<
MessageReminder
.
Complex
ref=
{
messageReminderComplexRef
}
/>
{
/* <Button ref={audioRef} onClick={() => { socket.play() }}>声音</Button> */
}
</
ProLayout
>
);
...
...
src/models/messageReminder.js
deleted
100644 → 0
View file @
6c3c8269
import
{
apiUpdageBusinessMsgStatus
}
from
'
@/services/messageReminder
'
;
const
MessageReminderModel
=
{
namespace
:
'
messageReminder
'
,
state
:
{
unReadCount
:
0
,
// 未读总数
unReadData
:
[],
// 未读数据
},
effects
:
{
*
setUnReadData
({
payload
,
options
},
{
put
,
call
})
{
yield
setTimeout
(()
=>
{
put
({
type
:
'
setUnReadData
'
,
payload
,
options
,
});
});
},
*
setMarkRead
({
payload
,
options
=
{}
},
{
put
,
call
})
{
const
{
setLoading
}
=
options
;
if
(
setLoading
)
{
setLoading
(
true
);
}
const
res
=
yield
call
(
apiUpdageBusinessMsgStatus
,
payload
);
// console.log(res)
if
(
setLoading
)
{
setLoading
(
false
);
}
if
(
res
.
code
!==
'
0000
'
)
{
return
;
}
if
(
Object
.
hasOwnProperty
.
call
(
options
,
'
callback
'
)
&&
typeof
options
.
callback
===
'
function
'
)
{
options
.
callback
(
res
);
}
yield
put
({
type
:
'
updateUnReadData
'
,
payload
,
options
,
});
},
},
reducers
:
{
setUnReadData
(
state
,
{
payload
,
options
=
{}
})
{
const
currentData
=
[...
payload
,
...
state
.
unReadData
];
let
unReadCount
=
state
.
unReadCount
+
1
;
if
(
options
.
unReadCount
||
options
.
unReadCount
===
0
)
{
// eslint-disable-next-line prefer-destructuring
unReadCount
=
options
.
unReadCount
;
}
return
{
...
state
,
unReadData
:
currentData
,
unReadCount
};
},
updateUnReadData
(
state
,
{
payload
,
options
=
{}
})
{
// 删除已读的数据
const
currentData
=
state
.
unReadData
.
filter
(
message
=>
!
payload
.
idsList
.
includes
(
message
.
id
));
// 重置当前未读数量
const
unReadCount
=
currentData
.
length
;
// state.unReadCount - (options.readCount || payload.idsList.length || 1)
return
{
...
state
,
unReadCount
,
unReadData
:
currentData
};
},
},
};
export
default
MessageReminderModel
;
src/services/messageReminder.js
View file @
42a1a428
import
request
from
'
@/utils/request
'
;
import
config
from
'
../../config/env.config
'
;
const
{
msgApi
,
wsApi
}
=
config
;
export
const
getSocketUrl
=
({
token
,
channelId
})
=>
`
${
wsApi
}
/ws?token=
${
token
}
&channelId=
${
channelId
}
`
;
const
{
msgApi
}
=
config
;
/**
* @name 商户消息列表
...
...
src/utils/websocket.js
deleted
100644 → 0
View file @
6c3c8269
import
EventEmitter
from
'
events
'
;
import
{
Modal
}
from
'
antd
'
;
class
Socket
extends
EventEmitter
{
event
=
new
EventEmitter
();
constructor
(
options
)
{
super
();
this
.
options
=
options
;
this
.
reconnectCount
=
0
;
this
.
socket
=
null
;
this
.
taskRemindInterval
=
null
;
this
.
connected
=
false
;
this
.
waitingSendData
=
[];
this
.
heartBeatTimer
=
null
;
return
this
;
}
connection
=
()
=>
{
const
{
url
,
timeout
=
0
}
=
this
.
options
;
// 检测当前浏览器是什么浏览器来决定用什么socket
if
(
'
WebSocket
'
in
window
)
{
console
.
log
(
'
WebSocket
'
);
this
.
socket
=
new
WebSocket
(
url
);
}
else
if
(
'
MozWebSocket
'
in
window
)
{
console
.
log
(
'
MozWebSocket
'
);
// eslint-disable-next-line no-undef
this
.
socket
=
new
MozWebSocket
(
url
);
}
else
{
console
.
log
(
'
SockJS
'
);
// eslint-disable-next-line no-undef
this
.
socket
=
new
SockJS
(
url
);
}
// 链接回调
this
.
socket
.
onopen
=
this
.
onopen
;
this
.
socket
.
onmessage
=
this
.
onmessage
;
this
.
socket
.
onclose
=
this
.
onclose
;
this
.
socket
.
onerror
=
this
.
onerror
;
this
.
socket
.
sendMessage
=
this
.
sendMessage
;
// 检测返回的状态码 如果socket.readyState不等于1则连接失败,关闭连接
if
(
timeout
)
{
const
time
=
setTimeout
(()
=>
{
if
(
this
.
socket
&&
this
.
socket
.
readyState
!==
1
)
{
console
.
log
(
'
主动触发关闭
'
);
this
.
socket
.
close
();
}
clearTimeout
(
time
);
},
timeout
);
}
};
// 连接成功触发
onopen
=
()
=>
{
const
{
heartBeatTime
}
=
this
.
options
;
console
.
log
(
'
ws: 连接成功
'
,
new
Date
().
getTime
());
this
.
connected
=
true
;
this
.
heartBeat
(
heartBeatTime
);
this
.
checkWaitingData
();
this
.
event
.
emit
(
'
open
'
);
};
// 后端向前端推得数据
onmessage
=
msg
=>
{
console
.
log
(
'
ws:接收数据:
'
,
msg
);
this
.
event
.
emit
(
'
message
'
,
msg
);
// 打印出后端推得数据
};
// 关闭连接触发
onclose
=
e
=>
{
console
.
log
(
'
ws: 关闭连接
'
,
new
Date
().
getTime
());
this
.
connected
=
false
;
// 关闭将标识符改为true
if
(
this
.
heartBeatTimer
)
{
clearTimeout
(
this
.
heartBeatTimer
);
}
this
.
event
.
emit
(
'
close
'
,
e
);
// 最多重连10次
if
(
this
.
reconnectCount
>
10
)
{
this
.
reconnectCount
=
0
;
return
;
}
const
reconnect
=
()
=>
{
if
(
this
.
taskRemindInterval
)
{
clearTimeout
(
this
.
taskRemindInterval
);
}
this
.
taskRemindInterval
=
setTimeout
(()
=>
{
if
(
!
this
.
connected
)
{
this
.
reconnectCount
++
;
this
.
connection
();
reconnect
();
}
},
5000
);
};
if
(
process
.
env
.
NODE_ENV
===
'
production
'
)
{
reconnect
();
}
};
onerror
=
e
=>
{
try
{
this
.
socket
=
null
;
this
.
event
.
emit
(
'
error
'
,
e
);
}
catch
{
console
.
log
(
'
ws: error
'
,
e
);
}
};
sendMessage
=
value
=>
{
console
.
log
(
'
ws: send
'
,
value
);
// 向后端发送数据
if
(
this
.
socket
)
{
if
(
!
this
.
connected
)
{
this
.
waitingSendData
.
unshift
(
value
);
return
;
}
const
sendValue
=
typeof
value
===
'
string
'
?
value
:
JSON
.
stringify
(
value
);
if
(
this
.
socket
.
readyState
===
this
.
socket
.
OPEN
)
{
this
.
socket
.
send
(
sendValue
);
}
}
};
checkWaitingData
()
{
console
.
log
(
'
ws: checkWaitingData
'
,
this
.
waitingSendData
);
if
(
this
.
waitingSendData
.
length
)
{
this
.
sendMessage
(
this
.
waitingSendData
.
splice
(
0
,
1
));
this
.
checkWaitingData
();
}
}
// 保持连接-默认每3分钟重置一下服务器关闭时间
heartBeat
(
time
)
{
// console.log('ws: call heartBeat', new Date().getTime());
this
.
heartBeatTimer
=
setTimeout
(()
=>
{
// console.log('ws: sent heart beat', new Date().getTime());
this
.
sendMessage
(
'
HeartBeat
'
);
this
.
heartBeat
(
time
);
},
time
||
45000
);
}
}
export
default
Socket
;
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment