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/orders/Follow.jsx

270 lines
11 KiB
JavaScript

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

import useAuthStore from '@/stores/AuthStore'
import useFormStore from '@/stores/FormStore'
import { useOrderStore } from '@/stores/OrderStore'
import { isEmpty, groupBy, buildTree } from '@/utils/commons'
import { StarTwoTone, CalendarTwoTone, FolderOutlined, DeleteOutlined, ClockCircleOutlined, FormOutlined, DatabaseOutlined } from '@ant-design/icons'
import { Flex, Drawer, Radio, Divider, Segmented, Tree, Typography, Checkbox, Layout, Row, Col } from 'antd'
import { useEffect, useMemo, useState } from 'react'
import { InboxIcon, MailUnreadIcon, SendPlaneFillIcon } from '@/components/Icons'
import { useShallow } from 'zustand/react/shallow'
import EmailDetailInline from '../Conversations/Online/Components/EmailDetailInline'
import { getEmailDirAction, queryEmailListAction } from '@/actions/EmailActions'
import OrderProfile from '@/components/OrderProfile'
import Mailbox from './components/Mailbox'
const EmailDirTypeIcons = {
0: { component: FolderOutlined, color: '#ffe78f', className: 'text-blue-500' },
1: { component: FolderOutlined, color: '#ffe78f', className: 'text-blue-500' },
3: { component: InboxIcon, color: '', className: 'text-indigo-500' },
17: { component: InboxIcon, color: '', className: 'text-indigo-500' },
11: { component: MailUnreadIcon, color: '', className: 'text-indigo-500' },
4: { component: SendPlaneFillIcon, color: '', className: 'text-primary' },
2: { component: ClockCircleOutlined, color: '', className: 'text-yellow-500' },
5: { component: FormOutlined, color: '', className: 'text-blue-500' },
7: { component: DeleteOutlined, color: '', className: 'text-red-500' },
// '3': { component: MailCheckIcon, color: '', className: 'text-yellow-600' },
12: { component: DatabaseOutlined, color: '', className: 'text-blue-600' },
13: { component: () => null, color: '', className: '' },
14: { component: () => '❗', color: '', className: '' }, // 240002 较重要/高品牌价值客户
15: { component: () => '❣️', color: '', className: '' }, // 240003 很重要/高订单价值客户
}
const todoTypes = {
// 1新订单2未读消息3需一催4需二催5需三催6未处理邮件入境提醒coli_ordertype=7余款提醒coli_ordertype=8
1: '新订单',
2: '未读',
3: '一催',
4: '二催',
5: '三催',
6: '未处理',
7: '入境提醒',
8: '余款提醒',
}
const deptMap = new Map([
['1', 'CH'], // CH直销组
['2', 'CH大客户组'],
['7', '市场推广'],
['8', '德语市场'],
['9', '日语市场'],
['10', '商旅市场'],
['11', '法语市场'],
['12', '西语市场'],
['13', '英文在线组'],
['14', '商务Biztravel'],
['15', 'CH产品'],
['16', 'APP移动项目组'],
['17', 'ChinaTravel组'],
['18', 'CT市场'],
['20', '俄语市场'],
['21', '意语市场'],
['22', '爱游网'],
['23', '三峡站'],
['24', '桂林站'],
['25', '上海站'],
['26', '北京站'],
['27', '西藏站'],
['28', 'AH'], // AH亚洲项目组
['29', 'DMC地接组'],
['30', 'Trippest项目组'], //
['31', '花梨鹰'],
['32', 'Daytours板块'],
['33', 'GH'], // GH项目组
['34', 'trippest网站'],
['35', 'newsletter营销'],
])
function Follow() {
const orderList = useOrderStore((state) => state.orderList)
const fetchOrderList = useOrderStore((state) => state.fetchOrderList)
const [collapsed, setCollapsed] = useState(false)
const [loginUser, isPermitted] = useAuthStore((state) => [state.loginUser, state.isPermitted])
const { accountList } = loginUser
const accountListDEIMapped = useMemo(() => accountList.reduce((a, c) => ({ ...a, [c.OPI_DEI_SN]: c }), {}), [accountList])
const accountDEI = useMemo(() => {
return accountList.map((ele) => ({ key: ele.OPI_DEI_SN, value: ele.OPI_DEI_SN, label: deptMap.get(`${ele.OPI_DEI_SN}`) }))
}, [accountList])
const defaultStickyTree = useMemo(() => {
return accountList.reduce(
(a, ele) => ({
...a,
[ele.OPI_DEI_SN]: [
{
title: '今日任务',
key: ele.OPI_DEI_SN + '-today',
getMails: false,
icon: <StarTwoTone />,
children: [],
},
{
title: '待办任务',
key: ele.OPI_DEI_SN + '-todo',
getMails: false,
icon: <CalendarTwoTone />,
children: [],
},
],
}),
{},
)
}, [accountList])
const [activeEmailId, setActiveEmailId] = useState(0)
const [mailboxDir, setMailboxDir] = useState([])
const DirTypeIcon = ({ type }) => {
const Icon = EmailDirTypeIcons[type || '0']?.component || EmailDirTypeIcons['0'].component
const className = EmailDirTypeIcons[type || '0']?.className || EmailDirTypeIcons['0'].className
return <Icon className={className} />
}
const getOPIEmailDir = async (opi_sn = 0) => {
console.log('🌐requesting opi dir', opi_sn)
const x = await getEmailDirAction(opi_sn)
const mailboxSort = x //.sort(sortBy('MDR_Order'));
const dirs = mailboxSort.map((ele) => {
return { ...ele, icon: ele.ImageIndex !== void 0 ? <DirTypeIcon type={ele.ImageIndex} /> : false }
})
let tree = buildTree(dirs, { key: 'VKey', parent: 'VParent', name: 'VName', rootKey: 1 })
tree = tree.filter((ele) => ele.key !== 1)
// console.log(tree)
setMailboxDir(tree)
const level1 = tree.filter((ele) => !isEmpty(ele.children)).map((ele) => ele.key)
setExpandTree((pre) => [...pre, ...level1])
}
const getMailList = async ({ query, order }) => {
const opi_sn = accountListDEIMapped[activeAccount].OPI_SN
const x = await queryEmailListAction({ opi_sn, query, order })
}
const [deiStickyTree, setDeiStickyTree] = useState({})
const [stickyTree, setStickyTree] = useState([])
const [expandTree, setExpandTree] = useState([])
const [activeAccount, setActiveAccount] = useState()
const handleSwitchAccount = (value) => {
setActiveAccount(value)
setStickyTree(deiStickyTree[value] || [])
setExpandTree([`${value}-today`, `${value}-todo`])
const opi = accountListDEIMapped[value].OPI_SN
getOPIEmailDir(opi)
}
const handleTreeSelectGetMails = (selectedKeys, { node }) => {
// console.info('selectedKeys: ', selectedKeys, node)
if (node?.COLI_SN || node?._raw?.COLI_SN) {
// 固定列表; 邮箱文件夹
// get order mails
// console.log('get order mails', { order: { coli_sn: node?.COLI_SN || node?._raw?.COLI_SN, order_source_type: node?._raw?.OrderSourceType || 227001, vkey: node.key } })
getMailList({ order: { coli_sn: node?.COLI_SN || node?._raw?.COLI_SN, order_source_type: node?._raw?.OrderSourceType || 227001, vkey: node.key } })
} else if ([-227001, -227002].includes(node.key) || [-227001, -227002].includes(node.parent) || node?.getMails === false) {
// nothing, expand only
console.log('nothing')
} else {
// get mail list
console.log('get mail list')
getMailList({ query: { vkey: selectedKeys[0] } })
}
}
useEffect(() => {
fetchOrderList({ type: 'today' }, loginUser)
getOPIEmailDir()
return () => {}
}, [])
// 1新订单2未读消息3需一催4需二催5需三催6未处理邮件入境提醒coli_ordertype=7余款提醒coli_ordertype=8
useEffect(() => {
const byDEI = groupBy(orderList, 'OPI_DEI_SN')
// console.log(byDEI, 'byDEI')
const byState = Object.keys(byDEI).reduce((acc, key) => {
// const stickyIndex0 = byDEI[key].filter(ele => [1, 2, 6].includes(ele.COLI_StateCode))
// const stickyIndex1 = byDEI[key].filter(ele => ![1, 2, 6].includes(ele.COLI_StateCode))
const sticky = groupBy(byDEI[key], (ele) => ([1, 2, 6].includes(ele.coli_ordertype) ? 0 : 1))
// const sticky = groupBy(byDEI[key], ele => [1, 2, 6].includes(ele.COLI_StateCode) ? 'today' : 'todo');
// console.log(sticky, ';;;;');
// const deiName = deptMap.get(`${key}`);
const treeNode = [
{
title: '今日任务',
key: key + '-today',
getMails: false,
icon: <StarTwoTone />,
children: (sticky[0] || []).map((o) => ({ ...o, key: o.COLI_SN, title: `(${todoTypes[o.coli_ordertype] || o.COLI_State}) ${o.COLI_ID}` })),
},
{
title: '待办任务',
key: key + '-todo',
getMails: false,
icon: <CalendarTwoTone />,
children: (sticky[1] || []).map((o) => ({ ...o, key: o.COLI_SN, title: `(${todoTypes[o.coli_ordertype] || o.COLI_State}) ${o.COLI_ID}` })),
},
]
// { key, title: deiName, children: sticky[0] };
return { ...acc, [key]: treeNode }
}, defaultStickyTree)
setDeiStickyTree(byState)
const first = accountDEI[0].value
setExpandTree([`${first}-today`, `${first}-todo`])
setStickyTree(byState[first] || [])
return () => {}
}, [orderList])
return (
<>
<Layout>
<Layout.Sider width='300' theme='light' style={{ height: 'calc(100vh - 166px)' }}>
<Flex justify='start' align='start' vertical className='h-full'>
<Segmented className='w-full' block shape='round' options={accountDEI} value={activeAccount} onChange={handleSwitchAccount} />
<div className='overflow-y-auto flex-auto w-full [&_.ant-tree-switcher]:me-0 [&_.ant-tree-node-content-wrapper]:px-0 [&_.ant-tree-node-content-wrapper]:text-ellipsis [&_.ant-tree-node-content-wrapper]:overflow-hidden [&_.ant-tree-node-content-wrapper]:whitespace-nowrap'>
<Tree
key='sticky-today'
blockNode
showIcon
showLine
onSelect={handleTreeSelectGetMails}
onExpand={(expandedKeys) => setExpandTree(expandedKeys)}
expandedKeys={expandTree}
defaultExpandedKeys={expandTree}
defaultSelectedKeys={['today']}
treeData={[...(stickyTree || []), ...mailboxDir]}
titleRender={(node) => <Typography.Text ellipsis={{ tooltip: node.title }}>{node.title}</Typography.Text>}
/>
</div>
</Flex>
</Layout.Sider>
<Layout.Content style={{ maxHeight: 'calc(100vh - 166px)', height: 'calc(100vh - 166px)', minWidth: '360px' }}>
<Row>
<Col className='bg-white' span={14}>
<Mailbox />
</Col>
<Col span={10} style={{ height: 'calc(100vh - 166px)' }}>
<EmailDetailInline mailID={activeEmailId || 5291957} emailMsg={{}} variant={'outline'} size={'small'} />
</Col>
</Row>
</Layout.Content>
<Layout.Sider
zeroWidthTriggerStyle={{ top: '30px' }}
width='280'
style={{
backgroundColor: '#fff',
}}
collapsible
collapsed={collapsed}
onCollapse={(value) => setCollapsed(value)}
collapsedWidth={0}
reverseArrow={true}>
<OrderProfile />
</Layout.Sider>
</Layout>
</>
)
}
export default Follow