|
|
|
|
import { Conditional } from '@/components/Conditional'
|
|
|
|
|
import useAuthStore from '@/stores/AuthStore'
|
|
|
|
|
import useFormStore from '@/stores/FormStore'
|
|
|
|
|
import { useOrderStore } from '@/stores/OrderStore'
|
|
|
|
|
import { copy, isNotEmpty, isEmpty } from '@/utils/commons'
|
|
|
|
|
import { WhatsAppOutlined } from '@ant-design/icons'
|
|
|
|
|
import {
|
|
|
|
|
App, Badge,
|
|
|
|
|
Empty,
|
|
|
|
|
Flex,
|
|
|
|
|
Radio, Space, Switch, Table,
|
|
|
|
|
Tabs, Divider,
|
|
|
|
|
Tag, Tooltip
|
|
|
|
|
} from 'antd'
|
|
|
|
|
import dayjs from 'dayjs'
|
|
|
|
|
import { useCallback, useEffect, useState } from 'react'
|
|
|
|
|
import { Link } from 'react-router-dom'
|
|
|
|
|
import { useShallow } from 'zustand/react/shallow'
|
|
|
|
|
import { UNREAD_MARK } from '@/actions/ConversationActions';
|
|
|
|
|
import AdvanceSearchForm from './AdvanceSearchForm';
|
|
|
|
|
|
|
|
|
|
function OrderGroupTable({ formValues }) {
|
|
|
|
|
|
|
|
|
|
const orderColumns = [
|
|
|
|
|
{
|
|
|
|
|
title: '订单号',
|
|
|
|
|
dataIndex: 'COLI_ID',
|
|
|
|
|
width: 222,
|
|
|
|
|
render: (text, record) => {
|
|
|
|
|
let tagIcon = ''
|
|
|
|
|
|
|
|
|
|
if (record.COLI_LineGrade === 240003) tagIcon = <Tag color='red'>重点</Tag>
|
|
|
|
|
else if (record.COLI_LineGrade === 240002) tagIcon = <Tag color='green'>次重点</Tag>
|
|
|
|
|
else if (record.COLI_LineGrade === 240001) tagIcon = <Tag color='blue'>一般</Tag>
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<Space>
|
|
|
|
|
<Link to={`/order/chat/${record.COLI_SN}`} state={record}>
|
|
|
|
|
{text}
|
|
|
|
|
</Link>
|
|
|
|
|
{tagIcon}
|
|
|
|
|
</Space>
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
title: '客人姓名',
|
|
|
|
|
dataIndex: 'coli_guest',
|
|
|
|
|
render: (text, record) => {
|
|
|
|
|
let regularText = ''
|
|
|
|
|
if (record.buytime > 0) regularText = '(R' + record.buytime + ')'
|
|
|
|
|
return (
|
|
|
|
|
<Space>
|
|
|
|
|
<Conditional
|
|
|
|
|
condition={isNotEmpty(record.coli_guest_WhatsApp)}
|
|
|
|
|
whenTrue={<Tooltip title={record.coli_guest_WhatsApp}><WhatsAppOutlined className={['pl-1', record.last_received_time ? 'text-whatsapp' : 'text-neutral-500']} /></Tooltip>}
|
|
|
|
|
/>
|
|
|
|
|
{text + regularText}
|
|
|
|
|
<Badge
|
|
|
|
|
count={record.unread_msg >= UNREAD_MARK ? ' ' : record.unread_msg}
|
|
|
|
|
style={{
|
|
|
|
|
backgroundColor: '#52c41a',
|
|
|
|
|
}}
|
|
|
|
|
/>
|
|
|
|
|
</Space>
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
title: '订单状态',
|
|
|
|
|
dataIndex: 'COLI_State',
|
|
|
|
|
width: 140,
|
|
|
|
|
render: (text, record) => {
|
|
|
|
|
let extra = ''
|
|
|
|
|
if (record.coli_ordertype === 3 || record.coli_ordertype === 4 || record.coli_ordertype === 5) {
|
|
|
|
|
extra = '(' + (record.coli_ordertype - 2) + '催)'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<Space>
|
|
|
|
|
{extra}
|
|
|
|
|
{text}
|
|
|
|
|
</Space>
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
title: '报价 Title',
|
|
|
|
|
dataIndex: 'lettertitle',
|
|
|
|
|
ellipsis: true,
|
|
|
|
|
hidden: false,
|
|
|
|
|
// render: (text, record) => {
|
|
|
|
|
// return (
|
|
|
|
|
// <Tooltip title={text}>{text}</Tooltip>
|
|
|
|
|
// )
|
|
|
|
|
// }
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
title: '出发日期',
|
|
|
|
|
dataIndex: 'COLI_OrderStartDate',
|
|
|
|
|
width: 120,
|
|
|
|
|
hidden: false,
|
|
|
|
|
sortDirections: ['ascend', 'descend'],
|
|
|
|
|
sorter: (a, b) => {
|
|
|
|
|
const datejsA = isEmpty(a.COLI_OrderStartDate) ? 0 : new dayjs(a.COLI_OrderStartDate).valueOf()
|
|
|
|
|
const datejsB = isEmpty(b.COLI_OrderStartDate) ? 0 : new dayjs(b.COLI_OrderStartDate).valueOf()
|
|
|
|
|
return datejsA - datejsB
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
title: '客人最后一次回复时间',
|
|
|
|
|
dataIndex: 'last_received_time',
|
|
|
|
|
width: 180,
|
|
|
|
|
render: (text, record) => {
|
|
|
|
|
if (record.last_received_time) {
|
|
|
|
|
return new dayjs(record.last_received_time).format('YYYY-MM-DD HH:mm:ss')
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
title: '附加信息',
|
|
|
|
|
ellipsis: true,
|
|
|
|
|
dataIndex: 'COLI_Introduction',
|
|
|
|
|
},
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
const { notification } = App.useApp()
|
|
|
|
|
const [loading, setLoading] = useState(false)
|
|
|
|
|
const orderList = useOrderStore((state) => state.orderList)
|
|
|
|
|
const fetchOrderList = useOrderStore((state) => state.fetchOrderList)
|
|
|
|
|
const loginUser = useAuthStore((state) => state.loginUser)
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
let canSearch = true
|
|
|
|
|
|
|
|
|
|
if (formValues.type === 'advance') {
|
|
|
|
|
const copyObject = copy(formValues)
|
|
|
|
|
delete copyObject.type
|
|
|
|
|
const allEmpty = Object.values(copyObject).every(val => {
|
|
|
|
|
return val === null || val === '' || val === undefined
|
|
|
|
|
})
|
|
|
|
|
if (allEmpty) {
|
|
|
|
|
canSearch = false
|
|
|
|
|
notification.warning({
|
|
|
|
|
message: '温馨提示',
|
|
|
|
|
description: '请输入至少一个条件',
|
|
|
|
|
placement: 'top',
|
|
|
|
|
duration: 60,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (canSearch) {
|
|
|
|
|
setLoading(true)
|
|
|
|
|
fetchOrderList(formValues, loginUser)
|
|
|
|
|
.finally(() => setLoading(false))
|
|
|
|
|
.catch(reason => {
|
|
|
|
|
notification.error({
|
|
|
|
|
message: '查询出错',
|
|
|
|
|
description: reason.message,
|
|
|
|
|
placement: 'top',
|
|
|
|
|
duration: 60,
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}, [formValues])
|
|
|
|
|
|
|
|
|
|
const paginationProps = {
|
|
|
|
|
showQuickJumper: true,
|
|
|
|
|
showLessItems: true,
|
|
|
|
|
showSizeChanger: true,
|
|
|
|
|
showTotal: (total) => { return `总数:${total}` }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function groupByParam(array, param) {
|
|
|
|
|
return array.reduce((result, item) => {
|
|
|
|
|
(result[item[param]] = result[item[param]] || []).push(item)
|
|
|
|
|
return result
|
|
|
|
|
}, {})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const deptMap = new Map([
|
|
|
|
|
['1', '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亚洲项目组'],
|
|
|
|
|
['29', 'DMC地接组'],
|
|
|
|
|
['30', 'Trippest项目组'],
|
|
|
|
|
['31', '花梨鹰'],
|
|
|
|
|
['32', 'Daytours板块'],
|
|
|
|
|
['33', 'GH项目组'],
|
|
|
|
|
['34', 'trippest网站'],
|
|
|
|
|
['35', 'newsletter营销'],
|
|
|
|
|
])
|
|
|
|
|
|
|
|
|
|
const groupOrderData = groupByParam(orderList, 'OPI_DEI_SN')
|
|
|
|
|
const deptKeys = Object.keys(groupOrderData)
|
|
|
|
|
const deptItems = []
|
|
|
|
|
|
|
|
|
|
deptKeys.forEach((deptNo, index) => {
|
|
|
|
|
const deptOrderList = groupOrderData[deptNo]
|
|
|
|
|
// 1新订单;2未读消息;3需一催;4需二催;5需三催;6未处理邮件;入境提醒coli_ordertype=7,余款提醒coli_ordertype=8
|
|
|
|
|
const newOrderList = deptOrderList.filter((o) => {
|
|
|
|
|
return o.coli_ordertype === 1
|
|
|
|
|
})
|
|
|
|
|
const newMsgList = deptOrderList.filter((o) => {
|
|
|
|
|
return o.coli_ordertype === 2 || o.coli_ordertype === 6
|
|
|
|
|
})
|
|
|
|
|
const followUpList = deptOrderList.filter((o) => {
|
|
|
|
|
return o.coli_ordertype === 3 || o.coli_ordertype === 4 || o.coli_ordertype === 5
|
|
|
|
|
})
|
|
|
|
|
const entryList = deptOrderList.filter((o) => {
|
|
|
|
|
return o.coli_ordertype === 7
|
|
|
|
|
})
|
|
|
|
|
const paymentList = deptOrderList.filter((o) => {
|
|
|
|
|
return o.coli_ordertype === 8
|
|
|
|
|
})
|
|
|
|
|
if (formValues.type === 'today') {
|
|
|
|
|
deptItems.push(
|
|
|
|
|
{
|
|
|
|
|
key: index,
|
|
|
|
|
label: deptMap.get(deptNo),
|
|
|
|
|
children: <>
|
|
|
|
|
<Divider orientation='left'>新订单</Divider>
|
|
|
|
|
<Conditional
|
|
|
|
|
condition={newOrderList.length > 0}
|
|
|
|
|
whenTrue={<Table key={'newOrderTable' + deptNo} loading={loading} dataSource={newOrderList}
|
|
|
|
|
columns={orderColumns}
|
|
|
|
|
pagination={newOrderList.length <= 10 ? false : paginationProps} />}
|
|
|
|
|
whenFalse={<Empty />}
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
<Divider orientation='left'>新消息/老邮件</Divider>
|
|
|
|
|
<Conditional
|
|
|
|
|
condition={newMsgList.length > 0}
|
|
|
|
|
whenTrue={<Table key={'newMsgTable' + deptNo} loading={loading} dataSource={newMsgList}
|
|
|
|
|
columns={orderColumns}
|
|
|
|
|
pagination={newMsgList.length <= 10 ? false : paginationProps} />}
|
|
|
|
|
whenFalse={<Empty />}
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
<Divider orientation='left'>催信</Divider>
|
|
|
|
|
<Conditional
|
|
|
|
|
condition={followUpList.length > 0}
|
|
|
|
|
whenTrue={<Table key={'followUpTable' + deptNo} loading={loading} dataSource={followUpList}
|
|
|
|
|
columns={orderColumns}
|
|
|
|
|
pagination={followUpList.length <= 10 ? false : paginationProps} />}
|
|
|
|
|
whenFalse={<Empty />}
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
<Divider orientation='left'>余款收付</Divider>
|
|
|
|
|
<Conditional
|
|
|
|
|
condition={paymentList.length > 0}
|
|
|
|
|
whenTrue={<Table key={'paymentTable' + deptNo} loading={loading} dataSource={paymentList}
|
|
|
|
|
columns={orderColumns}
|
|
|
|
|
pagination={paymentList.length <= 10 ? false : paginationProps} />}
|
|
|
|
|
whenFalse={<Empty />}
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
<Divider orientation='left'>入境提醒</Divider>
|
|
|
|
|
<Conditional
|
|
|
|
|
condition={entryList.length > 0}
|
|
|
|
|
whenTrue={<Table key={'entryTable' + deptNo} loading={loading} dataSource={entryList}
|
|
|
|
|
columns={orderColumns}
|
|
|
|
|
pagination={entryList.length <= 10 ? false : paginationProps} /> }
|
|
|
|
|
whenFalse={<Empty />}
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
</>
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
} else {
|
|
|
|
|
deptItems.push(
|
|
|
|
|
{
|
|
|
|
|
key: index,
|
|
|
|
|
label: deptMap.get(deptNo),
|
|
|
|
|
children: <>
|
|
|
|
|
<Table key={'advanceOrderTable' + deptNo} loading={loading} dataSource={deptOrderList}
|
|
|
|
|
columns={orderColumns}
|
|
|
|
|
pagination={deptOrderList.length <= 10 ? false : paginationProps} />
|
|
|
|
|
</>
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<Conditional
|
|
|
|
|
condition={orderList.length > 0}
|
|
|
|
|
whenTrue={<Tabs defaultActiveKey={0} items={deptItems} />}
|
|
|
|
|
whenFalse={<Empty />}
|
|
|
|
|
/>
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function Follow() {
|
|
|
|
|
|
|
|
|
|
const [formValues, setFormValues] = useFormStore(useShallow((state) => [state.orderFollowForm, state.setOrderFollowForm]))
|
|
|
|
|
const [advanceChecked, toggleAdvance] = useFormStore(useShallow((state) => [state.orderFollowAdvanceChecked, state.setOrderFollowAdvanceChecked]))
|
|
|
|
|
|
|
|
|
|
const handleSubmit = useCallback((values) => {
|
|
|
|
|
setFormValues({ ...values, type: 'advance' })
|
|
|
|
|
}, [])
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<>
|
|
|
|
|
<Space direction='vertical' size='large' style={{ width: '100%' }}>
|
|
|
|
|
<Flex gap='large' justify='start' align='center' horizontal='true'>
|
|
|
|
|
<Radio.Group
|
|
|
|
|
options={[
|
|
|
|
|
{ label: '今日任务', value: 'today' },
|
|
|
|
|
{ label: '重点订单', value: 'zhongdian' },
|
|
|
|
|
{ label: '次重点客户', value: 'qianli' },
|
|
|
|
|
{ label: '成行', value: 'chengxing' },
|
|
|
|
|
{ label: '走团中', value: 'zoutuan' },
|
|
|
|
|
{ label: '走团后一月', value: 'zoutuanhou' }
|
|
|
|
|
]}
|
|
|
|
|
value={formValues.type}
|
|
|
|
|
onChange={({ target: { value } }) => {
|
|
|
|
|
setFormValues({
|
|
|
|
|
...formValues,
|
|
|
|
|
type: value
|
|
|
|
|
})
|
|
|
|
|
}}
|
|
|
|
|
optionType='button'
|
|
|
|
|
buttonStyle='solid'
|
|
|
|
|
disabled={advanceChecked}
|
|
|
|
|
/>
|
|
|
|
|
<Switch checkedChildren='高级查询' unCheckedChildren='高级查询'
|
|
|
|
|
checked={advanceChecked}
|
|
|
|
|
onChange={() => { toggleAdvance(!advanceChecked) }} />
|
|
|
|
|
</Flex>
|
|
|
|
|
<Conditional condition={advanceChecked} whenTrue={<AdvanceSearchForm onSubmit={handleSubmit} initialValues={formValues} />}
|
|
|
|
|
/>
|
|
|
|
|
<OrderGroupTable formValues={formValues} />
|
|
|
|
|
</Space>
|
|
|
|
|
</>
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export default Follow
|