You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Global-sales/src/views/DesktopApp.jsx

262 lines
7.2 KiB
JavaScript

import useAuthStore from '@/stores/AuthStore'
import useSnippetStore from '@/stores/SnippetStore'
import { useOrderStore } from '@/stores/OrderStore'
import useConversationStore from '@/stores/ConversationStore'
import { useThemeContext } from '@/stores/ThemeContext'
import { DownOutlined } from '@ant-design/icons'
import {
Avatar,
Col,
Dropdown,
Layout,
Menu,
Row,
Space,
Typography,
theme,
Badge,
Drawer,
} from 'antd'
import 'dayjs/locale/zh-cn'
import { useEffect, useState, useCallback, useRef } from 'react'
import { Link, NavLink, Outlet, useHref } from 'react-router-dom'
import '@/assets/App.css'
import AppLogo from '@/assets/highlights_travel_300_300.png'
import 'react-chat-elements/dist/main.css'
import ReloadPrompt from './ReloadPrompt'
import ClearCache from './ClearCache'
import SnippetList from '@/views/accounts/SnippetList'
import GeneratePayment from '@/views/accounts/GeneratePayment'
import { BUILD_VERSION, BUILD_DATE } from '@/config'
const { Header, Footer, Content } = Layout
const { Title } = Typography
function DesktopApp() {
const { colorPrimary } = useThemeContext()
const loginUser = useAuthStore((state) => state.loginUser)
const href = useHref()
const totalNotify = useConversationStore((state) => state.totalNotify)
const [
openSnippetDrawer,
closeSnippetDrawer,
snippetDrawerOpen,
] = useSnippetStore((state) => [
state.openDrawer,
state.closeDrawer,
state.drawerOpen,
])
const [
openPaymentDrawer,
closePaymentDrawer,
paymentDrawerOpen,
] = useOrderStore((state) => [
state.openDrawer,
state.closeDrawer,
state.drawerOpen,
])
const onClick = ({ key }) => {
if (key === 'snippet-list') {
openSnippetDrawer()
} else if (key == 'generate-payment') {
openPaymentDrawer()
}
}
let defaultPath = '/order/follow'
if (href !== '/') {
const splitPath = href.split('/')
if (splitPath.length > 2) {
defaultPath = '/' + splitPath[1] + '/' + splitPath[2]
}
}
const {
token: { colorBgContainer },
} = theme.useToken()
/**
* 标签页标题闪烁
*/
const [isTitleVisible, setIsTitleVisible] = useState(true)
const step = useCallback(() => {
document.title = isTitleVisible
? `🔔🔥💬【${totalNotify}条新消息】`
: '______________';
setIsTitleVisible(!isTitleVisible);
}, [isTitleVisible, totalNotify]);
useEffect(() => {
let intervalId;
if (totalNotify > 0) {
if ('setAppBadge' in navigator) {
navigator.setAppBadge(totalNotify).catch(() => {});
}
intervalId = setInterval(step, 1000); // 1000ms = 1s
} else {
document.title = '销售平台';
if ('clearAppBadge' in navigator) {
navigator.clearAppBadge().catch(() => {})
}
}
return () => {
if (intervalId) {
clearInterval(intervalId);
}
};
}, [totalNotify, isTitleVisible]);
return (
<Layout>
<Header
className='header'
style={{
position: 'sticky',
top: 0,
zIndex: 2,
width: '100%',
background: 'white',
}}>
<Drawer
title='图文集'
placement={'top'}
size={'large'}
onClose={() => closeSnippetDrawer()}
open={snippetDrawerOpen}
>
<SnippetList></SnippetList>
</Drawer>
<Drawer
title='支付链接'
placement={'top'}
size={'large'}
onClose={() => closePaymentDrawer()}
open={paymentDrawerOpen}
>
<GeneratePayment></GeneratePayment>
</Drawer>
<Row gutter={{ md: 24 }} align='middle'>
<Col flex='220px'>
<NavLink to='/'>
<img src={AppLogo} className='logo' alt='App logo' />
</NavLink>
<Title level={3}>销售平台</Title>
</Col>
<Col span={10}>
<Menu
mode='horizontal'
selectedKeys={[defaultPath]}
items={[
{
key: '/order/follow',
label: <Link to='/order/follow'>订单跟踪</Link>,
},
{
key: '/order/chat',
label: (
<Link to='/order/chat'>
在线聊天
<Badge
count={totalNotify > 0 ? totalNotify : undefined}
style={{
backgroundColor: '#52c41a',
}}
/>
</Link>
),
},
{
key: '/callcenter/call',
label: <Link to='/callcenter/call'>语音通话</Link>,
},
{
key: '/chat/history',
label: <Link to='/chat/history'>聊天记录</Link>,
},
{
key: '/customer_relation/index',
label: <Link to='/customer_relation/index'>客户运营</Link>,
},
]}
/>
</Col>
<Col
flex='auto'
style={{
color: 'white',
marginBottom: '0',
display: 'flex',
justifyContent: 'end',
}}>
<ReloadPrompt style={{marginRight: 'auto'}} />
<Dropdown
menu={{
items: [
{
label: <Link to='/account/profile'>个人资料</Link>,
key: 'profile',
},
{
label: '支付链接',
key: 'generate-payment',
},
{
label: '图文集',
key: 'snippet-list',
},
{ type: 'divider' },
{ label: <ReloadPrompt force />, key: 'reload' },
{ type: 'divider' },
{ label: <ClearCache />, key: 'clearcache' },
{ type: 'divider' },
{
label: <Link to='/p/dingding/logout'>退出</Link>,
key: 'logout',
},
],
onClick,
}}
trigger={['click']}>
<a
onClick={(e) => e.preventDefault()}
style={{ color: colorPrimary }}>
<Space>
<Avatar src={loginUser.avatarUrl}>
{loginUser?.username?.substring(1)}
</Avatar>
{loginUser.username}
<DownOutlined />
</Space>
</a>
</Dropdown>
</Col>
</Row>
</Header>
<Layout>
<Content
style={{
padding: 8,
margin: 0,
minHeight: 280,
background: colorBgContainer,
}}>
<Outlet />
</Content>
</Layout>
<Footer>
桂林海纳国际旅行社有限公司 Version: {BUILD_VERSION}({BUILD_DATE})
</Footer>
</Layout>
)
}
export default DesktopApp