Merge remote-tracking branch 'origin/main' into dev/chat

# Conflicts:
#	src/views/OrderFollow.jsx
dev/chat
lot 1 year ago
commit cf093c22ca

@ -5,8 +5,7 @@ import { createBrowserRouter, RouterProvider } from 'react-router-dom';
import { AuthContext } from '@/stores/AuthContext' import { AuthContext } from '@/stores/AuthContext'
import { ThemeContext } from '@/stores/ThemeContext' import { ThemeContext } from '@/stores/ThemeContext'
import ConversationProvider from '@/views/Conversations/ConversationProvider' import ConversationProvider from '@/views/Conversations/ConversationProvider'
import Auth from '@/stores/Auth' import AuthApp from '@/views/AuthApp'
import App from '@/views/App'
import Standlone from '@/views/Standlone' import Standlone from '@/views/Standlone'
import OrderFollow from '@/views/OrderFollow' import OrderFollow from '@/views/OrderFollow'
import ChatHistory from '@/views/ChatHistory' import ChatHistory from '@/views/ChatHistory'
@ -31,7 +30,7 @@ configure({
const router = createBrowserRouter([ const router = createBrowserRouter([
{ {
path: '/', path: '/',
element: <App />, element: <AuthApp />,
errorElement: <ErrorPage />, errorElement: <ErrorPage />,
children: [ children: [
{ index: true, element: <OrderFollow /> }, { index: true, element: <OrderFollow /> },

@ -1,17 +1,12 @@
import { useEffect } from 'react' import { useEffect } from 'react'
import { observer } from 'mobx-react'
import { import {
Row, Col, Space, Descriptions, Avatar Row, Col, Space, Descriptions, Avatar, Radio
} from 'antd' } from 'antd'
import { useAuthContext } from '@/stores/AuthContext' import { useAuthContext } from '@/stores/AuthContext'
function AccountProfile() { function AccountProfile() {
const { loginUser, permissionList } = useAuthContext() const { loginUser } = useAuthContext()
console.info('loginUser: ')
console.info(loginUser)
console.info('permissionList: ')
console.info(permissionList)
useEffect(() => { useEffect(() => {
// //
@ -21,9 +16,21 @@ function AccountProfile() {
return ( return (
<Row> <Row>
<Col span={12} offset={6}> <Col span={12} offset={6}>
<Descriptions title='个人信息' layout='vertical' column={2}> <Descriptions title='个人资料' layout='vertical' column={2}>
<Descriptions.Item label='名字'><Space size='middle'><Avatar src={loginUser.avatarUrl} />{loginUser.username}</Space></Descriptions.Item> <Descriptions.Item label='名字'><Space size='middle'><Avatar src={loginUser.avatarUrl} />{loginUser.username}</Space></Descriptions.Item>
<Descriptions.Item label='HT 账号'>{loginUser.accountName}</Descriptions.Item> <Descriptions.Item label='HT 账号'>
{loginUser.accountName}
<Radio.Group
options={[
{ label: 'LMY', value: '1' },
{ label: 'christy', value: '2' },
{ label: 'LMYGH', value: '3' }
]}
value='2'
optionType='button'
buttonStyle='solid'
/>
</Descriptions.Item>
<Descriptions.Item label='手机'>{loginUser.stateCode} {loginUser.mobile}</Descriptions.Item> <Descriptions.Item label='手机'>{loginUser.stateCode} {loginUser.mobile}</Descriptions.Item>
<Descriptions.Item label='邮件'>{loginUser.email}</Descriptions.Item> <Descriptions.Item label='邮件'>{loginUser.email}</Descriptions.Item>
</Descriptions> </Descriptions>
@ -32,4 +39,4 @@ function AccountProfile() {
) )
} }
export default observer(AccountProfile) export default AccountProfile

@ -1,22 +1,22 @@
import { Outlet, Link, useHref, NavLink } from 'react-router-dom'; import { Outlet, Link, useHref, NavLink } from 'react-router-dom'
import { Layout, Menu, ConfigProvider, theme, Empty, Row, Col, Dropdown, Space, Typography, App as AntApp } from 'antd'; import { Layout, Menu, ConfigProvider, theme, Empty, Row, Col, Avatar, Dropdown, Space, Typography, App as AntApp } from 'antd'
import { DownOutlined } from '@ant-design/icons'; import { DownOutlined } from '@ant-design/icons'
import ErrorBoundary from '@/components/ErrorBoundary'; import ErrorBoundary from '@/components/ErrorBoundary'
import zhLocale from 'antd/locale/zh_CN'; import zhLocale from 'antd/locale/zh_CN'
import { useThemeContext } from '@/stores/ThemeContext'; import { useThemeContext } from '@/stores/ThemeContext'
import { useAuthContext } from '@/stores/AuthContext' import { useAuthContext } from '@/stores/AuthContext'
import 'dayjs/locale/zh-cn'; import 'dayjs/locale/zh-cn'
import 'react-chat-elements/dist/main.css' import 'react-chat-elements/dist/main.css'
import '@/assets/App.css'; import '@/assets/App.css'
import AppLogo from '@/assets/logo-gh.png'; import AppLogo from '@/assets/logo-gh.png'
import { isEmpty } from '@/utils/commons'; import { isEmpty } from '@/utils/commons'
const { Header, Footer, Content } = Layout const { Header, Footer, Content } = Layout
const { Title } = Typography const { Title } = Typography
// AuthApp // AuthApp
function App() { function AuthApp() {
const { colorPrimary, borderRadius } = useThemeContext() const { colorPrimary, borderRadius } = useThemeContext()
const { loginUser, permissionList } = useAuthContext() const { loginUser, permissionList } = useAuthContext()
@ -90,10 +90,7 @@ function App() {
trigger={['click']} trigger={['click']}
> >
<a onClick={(e) => e.preventDefault()} style={{ color: colorPrimary }}> <a onClick={(e) => e.preventDefault()} style={{ color: colorPrimary }}>
<Space> <Space><Avatar src={loginUser.avatarUrl} />廖一军<DownOutlined /></Space>
廖一军
<DownOutlined />
</Space>
</a> </a>
</Dropdown> </Dropdown>
@ -119,4 +116,4 @@ function App() {
) )
} }
export default App export default AuthApp

@ -1,14 +1,14 @@
import { useNavigate } from 'react-router-dom' import { useNavigate } from 'react-router-dom'
import { useRef, useEffect, useState } from 'react' import { memo, useCallback, useEffect, useRef, useState } from 'react';
import { Row, Col, Divider, Table , Card, Button, Input, import { Row, Col, Divider, Table , Card, Button, Input,
Space, Empty, Radio, AutoComplete, DatePicker, Spin, List, Avatar Space, Empty, Radio, Select, DatePicker, Form, List, Avatar
} from 'antd' } from 'antd'
import { import {
StarFilled, ZoomInOutlined, StarOutlined, SearchOutlined StarFilled, ZoomInOutlined, StarOutlined, SearchOutlined
} from '@ant-design/icons' } from '@ant-design/icons'
const { Search } = Input; const { Search } = Input
const { RangePicker } = DatePicker; const { RangePicker } = DatePicker
const data = [ const data = [
{ {
@ -27,67 +27,86 @@ const data = [
title: 'Hailey', title: 'Hailey',
content: 'Disregard my first email- I was using Siri and didn\'t realize all the typos. ' content: 'Disregard my first email- I was using Siri and didn\'t realize all the typos. '
}, },
]; ]
const SearchForm = memo(function ({ onSubmit }) {
console.info('SearchForm')
const [form] = Form.useForm()
function handleSubmit(values) {
onSubmit?.(values)
}
return (
<Form
layout={'inline'}
form={form}
initialValues={{ orderLabel: '全部' }}
onFinish={handleSubmit}
style={{
maxWidth: 'none',
}}
>
<Form.Item label='客人' name='orderLabel' style={{width: '200px'}}>
<Select
showSearch
placeholder='Select a person'
optionFilterProp='children'
filterOption={(input, option) =>
(option?.label ?? '').toLowerCase().includes(input.toLowerCase())}
options={[
{
value: 'jack',
label: 'Jack',
},
{
value: 'lucy',
label: 'Lucy',
},
{
value: 'tom',
label: 'Tom',
},
]}
/>
</Form.Item>
<Form.Item label='关键词' name='orderNumber'>
<Input placeholder='关键词' allowClear />
</Form.Item>
<Form.Item label='日期' name='startDate'>
<RangePicker />
</Form.Item>
<Form.Item >
<Button type='primary' htmlType='submit'>搜索</Button>
</Form.Item>
</Form>
)
})
function ChatHistory() { function ChatHistory() {
useEffect(() => { const [formValues, setFormValues] = useState({})
const handleSubmit = useCallback((values) => {
setFormValues({...values})
}, []) }, [])
return ( return (
<Spin spinning={false} delay={500}> <>
<Space direction='vertical' style={{ width: '100%' }}> <SearchForm onSubmit={handleSubmit} />
<Row gutter={[16, 16]} justify='start' align='middle'>
<Col span={5}>
<AutoComplete
style={{ width: '100%' }}
placeholder='客人'
onChange={(value) => {
setKeyword(value)
}}
filterOption={(inputValue, option) =>
option.value.toUpperCase().indexOf(inputValue.toUpperCase()) !== -1
}
/>
</Col>
<Col span={6}>
<Input placeholder="关键词" allowClear />
</Col>
<Col span={4}>
<RangePicker />
</Col>
<Col span={2}>
<Button icon={<SearchOutlined />} onClick={() => {
search()
}}>搜索</Button>
</Col>
</Row>
</Space>
<Divider plain orientation='left'></Divider> <Divider plain orientation='left'></Divider>
<Space <List
direction='vertical' itemLayout='horizontal'
size='middle' dataSource={data}
style={{ renderItem={(item, index) => (
display: 'flex', <List.Item>
}} <List.Item.Meta
> avatar={<Avatar src={`https://api.dicebear.com/7.x/miniavs/svg?seed=${index}`} />}
<List title={<a href='https://ant.design'>{item.title}</a>}
itemLayout="horizontal" description={item.content}
dataSource={data} />
renderItem={(item, index) => ( </List.Item>
<List.Item> )}
<List.Item.Meta />
avatar={<Avatar src={`https://api.dicebear.com/7.x/miniavs/svg?seed=${index}`} />} </>
title={<a href="https://ant.design">{item.title}</a>}
description={item.content}
/>
</List.Item>
)}
/>
</Space>
</Spin>
) )
} }

@ -1,11 +1,21 @@
import { memo, useCallback, useEffect, useState } from 'react'
import { Link } from 'react-router-dom';
import {
Badge, Divider, Table, Button, Input,
Space, Tag, Radio, Select, Flex, Form, Switch, DatePicker, App
} from 'antd'
import { Conditional } from '@/components/Conditional' import { Conditional } from '@/components/Conditional'
import { useAuthContext } from '@/stores/AuthContext' import { useAuthContext } from '@/stores/AuthContext'
import {
App,
Badge,
Button,
DatePicker,
Divider,
Flex, Form,
Input,
Radio, Select,
Space,
Switch,
Table,
Tag
} from 'antd'
import { memo, useCallback, useEffect, useState } from 'react'
import { NavLink } from 'react-router-dom'
const { RangePicker } = DatePicker const { RangePicker } = DatePicker
@ -18,7 +28,7 @@ const AdvanceSearchForm = memo(function ({ onSubmit }) {
<Form <Form
layout={'inline'} layout={'inline'}
form={form} form={form}
initialValues={{ orderLabel: '全部' }} initialValues={{ orderLabel: '全部', orderStatus: '全部' }}
onFinish={handleSubmit} onFinish={handleSubmit}
style={{ style={{
maxWidth: 'none', maxWidth: 'none',
@ -30,18 +40,9 @@ const AdvanceSearchForm = memo(function ({ onSubmit }) {
width: 100, width: 100,
}} }}
options={[ options={[
{ { value: '240003', label: '重点' },
value: '潜力', { value: '240002', label: '潜力' },
label: '潜力', { value: '240001', label: '休眠' }
},
{
value: '重点',
label: '重点',
},
{
value: '休眠',
label: '休眠',
}
]} ]}
/> />
</Form.Item> </Form.Item>
@ -81,7 +82,7 @@ const AdvanceSearchForm = memo(function ({ onSubmit }) {
<Form.Item label='订单号' name='orderNumber'> <Form.Item label='订单号' name='orderNumber'>
<Input placeholder='订单号' allowClear /> <Input placeholder='订单号' allowClear />
</Form.Item> </Form.Item>
<Form.Item label='出发日期' name='startDate'> <Form.Item label='出发日期' name='startDateRange'>
<RangePicker /> <RangePicker />
</Form.Item> </Form.Item>
<Form.Item > <Form.Item >
@ -97,26 +98,23 @@ function OrderList({ formValues }) {
{ {
title: '订单号', title: '订单号',
dataIndex: 'COLI_ID', dataIndex: 'COLI_ID',
key: 'COLI_ID',
width: 222, width: 222,
render: (text, record) => { render: (text, record) => {
if (record.COLI_LineGrade === 240003) return <Space size='middle'>{text}<Tag color='red'>重点</Tag></Space> if (record.COLI_LineGrade === 240003) return <Space>{text}<Tag color='red'>重点</Tag></Space>
else if (record.COLI_LineGrade === 240002) return <Space size='middle'>{text}<Tag color='green'>潜力</Tag></Space> else if (record.COLI_LineGrade === 240002) return <Space>{text}<Tag color='green'>潜力</Tag></Space>
else if (record.COLI_LineGrade === 240001) return <Space size='middle'>{text}<Tag color='blue'>休眠</Tag></Space> else if (record.COLI_LineGrade === 240001) return <Space>{text}<Tag color='blue'>休眠</Tag></Space>
else return <Space size='middle'>{text}</Space> else return <Space>{text}</Space>
} }
}, },
{ {
title: '客人姓名', title: '客人姓名',
dataIndex: 'coli_guest', dataIndex: 'coli_guest',
key: 'coli_guest',
render: (text, record) => { render: (text, record) => {
let regularText = '' let regularText = ''
if (record.buytime > 0) regularText = '(R' + record.buytime + ')' if (record.buytime > 0) regularText = '(R' + record.buytime + ')'
return ( return (
<Space size='middle'> <Space>
{/* <a>{text + regularText}</a> */} <NavLink to={`/order/chat/${record.COLI_SN}`}>{text + regularText}</NavLink>
<Link to={'/order/chat/' + record.COLI_SN}>{text + regularText}</Link>
<Badge <Badge
count={record.unread_msg} count={record.unread_msg}
style={{ style={{
@ -130,7 +128,6 @@ function OrderList({ formValues }) {
{ {
title: '订单状态', title: '订单状态',
dataIndex: 'COLI_State', dataIndex: 'COLI_State',
key: 'COLI_State',
width: 120, width: 120,
render: (text, record) => { render: (text, record) => {
let extra = '' let extra = ''
@ -143,23 +140,20 @@ function OrderList({ formValues }) {
{ {
title: '报价title', title: '报价title',
dataIndex: 'lettertitle', dataIndex: 'lettertitle',
key: 'lettertitle',
ellipsis: true, ellipsis: true,
}, },
{ {
title: '客人最后一次回复时间', title: '客人最后一次回复时间',
dataIndex: 'last_received_time', dataIndex: 'last_received_time',
key: 'last_received_time',
}, },
{ {
title: '附加信息', title: '附加信息',
dataIndex: 'COLI_Introduction', dataIndex: 'COLI_Introduction',
key: 'COLI_Introduction',
}, },
] ]
const { notification } = App.useApp() const { notification } = App.useApp()
const [orderData, setOrderData] = useState([]) const [orderData, setOrderData] = useState([])
const [loading, setLoading] = useState(false) const [loading, setLoading] = useState(false)
const { loginUser } = useAuthContext() const { loginUser } = useAuthContext()
useEffect(() => { useEffect(() => {
@ -168,7 +162,7 @@ function OrderList({ formValues }) {
.then(response => response.json()) .then(response => response.json())
.then(json => { .then(json => {
if (json.errcode === 0) { if (json.errcode === 0) {
setOrderData([...json.result]) setOrderData(json.result.map((order) => { return {...order, key: order.COLI_ID}}))
} else { } else {
notification.error({ notification.error({
message: '查询出错', message: '查询出错',
@ -190,7 +184,7 @@ function OrderList({ formValues }) {
}, [formValues]) }, [formValues])
return ( return (
<Table loading={loading} dataSource={orderData} columns={orderColumns} /> <Table key='Order Table' loading={loading} dataSource={orderData} columns={orderColumns} />
) )
} }
function OrderFollow() { function OrderFollow() {

@ -1,14 +1,5 @@
import { useNavigate } from 'react-router-dom' import { Button, DatePicker, Divider, Form, Input, Select, Table } from 'antd';
import { memo, useRef, useCallback, useEffect, useState } from 'react' import { memo, useCallback, useEffect, useRef, useState } from 'react';
import {
Row, Col, Divider, Table, Card, Button, Input,
Space, Segmented, Radio, Select, Flex, Spin, Form, Switch, DatePicker, List, Avatar
} from 'antd'
import {
StarFilled, ZoomInOutlined, StarOutlined, SearchOutlined, ImportOutlined
} from '@ant-design/icons'
import {useGetJson} from '@/hooks/userFetch'
const { RangePicker } = DatePicker const { RangePicker } = DatePicker
@ -71,8 +62,7 @@ const dataSource = [
}, },
]; ];
const AdvanceSearchForm = memo(function ({ onSubmit }) { const SearchForm = memo(function ({ onSubmit }) {
console.info('AdvanceSearchForm')
const [form] = Form.useForm() const [form] = Form.useForm()
function handleSubmit(values) { function handleSubmit(values) {
onSubmit?.(values) onSubmit?.(values)
@ -155,22 +145,18 @@ const AdvanceSearchForm = memo(function ({ onSubmit }) {
}) })
const SalesTable = function({formValues}) { const SalesTable = function({formValues}) {
console.info('SalesTable') const isMounted = useRef(false)
console.info(formValues)
const isMounted = useRef(false)
const [salesData, setSalesData] = useState([]) const [salesData, setSalesData] = useState([])
const [loading, setLoading] = useState(false) const [loading, setLoading] = useState(false)
useEffect(() => { useEffect(() => {
console.info('SalesTable.useEffect')
console.info(isMounted)
setLoading(true) setLoading(true)
// setSalesData([]) //
setTimeout(() => { setTimeout(() => {
const randomData = dataSource.map(data => { const randomData = dataSource.map(data => {
data.travelAdvisor = 'Albee' + Math.floor(Math.random() * (100 - 2 + 1) + 2)
data.important = Math.floor(Math.random() * (100 - 2 + 1) + 2) data.important = Math.floor(Math.random() * (100 - 2 + 1) + 2)
data.star = Math.floor(Math.random() * (100 - 2 + 1) + 2)
data.ing = Math.floor(Math.random() * (100 - 2 + 1) + 2)
return data return data
}) })
setSalesData([...randomData]) setSalesData([...randomData])
@ -216,7 +202,7 @@ function SalesManagement() {
return ( return (
<> <>
<AdvanceSearchForm onSubmit={handleSubmit} /> <SearchForm onSubmit={handleSubmit} />
<Divider plain orientation='left'></Divider> <Divider plain orientation='left'></Divider>
<SalesTable formValues={formValues} /> <SalesTable formValues={formValues} />
</> </>

Loading…
Cancel
Save