开发: 添加客户列表

This commit is contained in:
zhengw
2023-04-18 17:28:06 +08:00
parent 97348fea9e
commit 079739223a
10 changed files with 456 additions and 269 deletions

View File

@@ -69,7 +69,7 @@ export const formatTags = (data: any) => {
if (data) {
try {
const tags = JSON.parse(data);
if (Array.isArray(tags)) {
if (Array.isArray(tags) && tags.length) {
return (
<>
{tags.map((item) => {
@@ -82,11 +82,9 @@ export const formatTags = (data: any) => {
</>
);
}
} catch (e) {
return <></>;
} catch (e) {}
}
}
return <></>;
return <div></div>;
};
type IGroupIcon = {

View File

@@ -22,7 +22,14 @@ export const Gender: React.FC<IProps> = (props) => {
</svg>
)}
</>
) : null}
) : (
<svg viewBox="0 0 1024 1024" width="16" height="16">
<path
d="M880.864 704.346c-56.813-25.397-141.118-90.818-265.945-113.298 31.924-34.36 56.084-88.097 80.937-151.754 14.403-36.893 11.935-68.343 11.935-113.121 0-33.073 6.193-86.156-1.97-115.329-27.533-98.59-97.1-125.79-178.61-125.79-81.577 0-151.229 27.328-178.71 126.087-8.097 29.083-1.888 82.044-1.888 115.037 0 44.875-2.422 76.432 12.019 113.383 25.044 63.984 48.854 117.644 80.655 151.86-123.826 22.89-207.498 87.822-263.95 113.138C58.523 756.945 57.95 814.296 57.95 814.296v97.42l940.724-0.112v-97.308s-0.547-57.548-117.809-109.95z"
fill="#1890ff"
></path>
</svg>
)}
</>
);
};

View File

@@ -150,7 +150,7 @@
pointer-events: none;
&.show {
z-index: 1;
z-index: 11;
transform: translateY(0px);
visibility: visible;
opacity: 1;

View File

@@ -109,8 +109,8 @@ const ChatLogs: React.FC = () => {
setChatLogLoading(false);
isAllChatRef.current = count < param.page_count * param.curr_page;
if (res.err_code == 0) {
if (Array.isArray(res.data) && res.data.length) {
let arr: IChat[] = [];
if (Array.isArray(res.data) && res.data.length) {
const temp = res.data.reverse();
const mark = { curr_page: param.curr_page, msg_time: temp[temp.length - 1].msg_time };
if (param.curr_page == 1) {
@@ -140,8 +140,8 @@ const ChatLogs: React.FC = () => {
// }
// });
// }
setChatLogs(arr);
}
setChatLogs(arr);
}
});
};
@@ -708,6 +708,18 @@ const ChatLogs: React.FC = () => {
</div>
</div>
<div>{selectCustFollow?.remark}</div>
<div
style={{
paddingTop: 12,
marginBottom: 12,
paddingBottom: 12,
borderBottom: '1px solid #ddd',
fontSize: 16,
fontWeight: 'bold',
}}
>
</div>
{formatTags(selectCustFollow?.tags)}
</div>
) : (

View File

@@ -0,0 +1,17 @@
.modalAvatar {
display: flex;
align-items: center;
justify-content: center;
width: 60px;
height: 60px;
margin-right: 12px;
overflow: hidden;
background-color: #69b1ff;
border-radius: 6px;
img {
max-width: 100%;
max-height: 100%;
object-fit: cover;
}
}

View File

@@ -1,85 +1,92 @@
import { SearchBarPlugin, SearchBottonsCardPlugin } from '@/components/SearchBarPlugin';
import { post } from '@/services/ajax';
import { AddWay, CustType } from '@/services/config';
import { PageContainer } from '@ant-design/pro-components';
import { Button, Col, DatePicker, Drawer, Form, Input, Pagination, Row, Table } from 'antd';
import {
Button,
Col,
DatePicker,
Drawer,
Form,
Image,
Input,
Pagination,
Popover,
Row,
Select,
Table,
Tag,
} from 'antd';
import { stringify } from 'qs';
import React, { useEffect, useState } from 'react';
import { IStaffsItem } from '../ChatLogs/ChatLogsType';
import { formatTags } from '../ChatLogs/ChatUtils';
import { Gender } from '../ChatLogs/components/Gender';
import styles from './index.module.scss';
interface IDepartment {
children: null | IDepartment[];
department_leader: string;
id: number;
interface ICustItem {
add_way: number;
avatar: string;
create_time: string;
cust_id: string;
description: string;
gender: number;
name: string;
parent_id: number;
sort: number;
}
interface IStaffsData {
count: number;
data?: IStaffsItem[];
oper_user_id: string;
remark: string;
remark_mobiles: string;
state: number;
tags: string;
type: number;
user_id: string;
}
type Param = {
curr_page: number;
page_count: number;
dep_id: number;
type?: number | string;
name?: string;
position?: string;
telephone?: string;
mobile?: string;
add_way?: string;
create_timeL?: string;
create_timeU?: string;
};
const CustomList: React.FC = () => {
const [param] = useState<Param>({
curr_page: 1,
page_count: 20,
dep_id: 0,
type: '',
name: '',
add_way: '',
create_timeL: '',
create_timeU: '',
});
const [departmentID, setDepartmentsID] = useState<number>(0);
const [departmentsList, setDepartmentsList] = useState<IDepartment[]>([]);
const [staffsData, setStaffsData] = useState<IStaffsData>({ count: 0, data: [] });
const [loadingL, setLoadingL] = useState(false);
const [custsList, setCustsList] = useState<ICustItem[]>([]);
const [count, setCount] = useState(0);
const [loading, setLoading] = useState(false);
const [open, setOpen] = useState(false);
const [record, setRecord] = useState<IStaffsItem>();
const [record, setRecord] = useState<ICustItem>();
const getStaffsList = () => {
const getCustsList = () => {
setLoading(true);
post({ url: '/Staffs/List', data: stringify(param) }).then((res) => {
post({ url: '/CustFollows/CustsList', data: stringify(param) }).then((res) => {
setLoading(false);
if (res.err_code == 0) {
if (!Array.isArray(res.data)) {
res.data = [];
}
setStaffsData(res as IStaffsData);
}
});
};
const getDepartmentsList = () => {
setLoadingL(true);
post({ url: '/Departments/List' }).then((res) => {
setLoadingL(false);
if (res.err_code == 0) {
if (Array.isArray(res.data) && res.data.length) {
param.dep_id = res.data[0].id;
setDepartmentsID(param.dep_id);
setDepartmentsList(res.data);
getStaffsList();
if (Array.isArray(res.data)) {
setCustsList(res.data);
}
setCount(res.count || 0);
}
});
};
const page = (page: number) => {
param.curr_page = page;
getStaffsList();
getCustsList();
};
useEffect(() => {
getDepartmentsList();
getCustsList();
}, []);
return (
@@ -88,9 +95,10 @@ const CustomList: React.FC = () => {
<SearchBarPlugin>
<Form autoComplete="off">
<Row gutter={{ xs: 0, sm: 16 }}>
<Col xs={24} sm={12} md={8}>
<Col xs={24} sm={12} lg={8} xxl={6}>
<Form.Item label="客户名称">
<Input
placeholder="请输入客户名称"
autoComplete="off"
onChange={(e) => {
param.name = e.target.value.trim();
@@ -100,54 +108,58 @@ const CustomList: React.FC = () => {
/>
</Form.Item>
</Col>
<Col xs={24} sm={12} md={8}>
<Form.Item label={<span style={{ textIndent: '2em' }}></span>}>
<Input
autoComplete="off"
onChange={(e) => {
param.position = e.target.value.trim();
<Col xs={24} sm={12} lg={8} xxl={6}>
<Form.Item label={<span></span>}>
<Select
defaultValue={param.type}
style={{ width: '100%' }}
onChange={(val) => {
param.type = val;
}}
allowClear
onPressEnter={() => page(1)}
/>
>
<Select.Option value=""></Select.Option>
{Object.keys(CustType).map((key) => {
return (
<Select.Option key={key} value={key}>
{CustType[key]}
</Select.Option>
);
})}
</Select>
</Form.Item>
</Col>
<Col xs={24} sm={12} md={8}>
<Form.Item label={<span style={{ textIndent: '1em' }}></span>}>
<Input
autoComplete="off"
onChange={(e) => {
param.mobile = e.target.value.trim();
<Col xs={24} sm={12} lg={8} xxl={6}>
<Form.Item label={<span></span>}>
<Select
defaultValue={param.add_way}
style={{ width: '100%' }}
onChange={(val) => {
param.add_way = val;
}}
allowClear
onPressEnter={() => page(1)}
/>
>
<Select.Option value=""></Select.Option>
{Object.keys(AddWay).map((key) => {
return (
<Select.Option key={key} value={key}>
{AddWay[key]}
</Select.Option>
);
})}
</Select>
</Form.Item>
</Col>
<Col xs={24} sm={12} md={8}>
<Form.Item label={<span style={{ textIndent: '1em' }}></span>}>
<Col xs={24} sm={12} lg={8} xxl={6}>
<Form.Item label={<span></span>}>
<DatePicker.RangePicker
style={{ width: '100%' }}
onChange={(dates, dateStrings) => {
console.log(dates, dateStrings);
// console.log(dateStrings);
param.create_timeL = dateStrings[0];
param.create_timeU = dateStrings[1];
}}
/>
</Form.Item>
</Col>
{/* <Col xs={24} sm={12} md={6}>
<Form.Item label="用户名">
<Select
defaultValue="lucy"
style={{ width: '100%' }}
onChange={() => {}}
options={[
{ value: 'jack', label: 'Jack' },
{ value: 'lucy', label: 'Lucy' },
{ value: 'Yiminghe', label: 'yiminghe' },
]}
/>
</Form.Item>
</Col> */}
</Row>
</Form>
</SearchBarPlugin>
@@ -167,58 +179,203 @@ const CustomList: React.FC = () => {
<Table
tableLayout="fixed"
size="middle"
dataSource={staffsData.data}
dataSource={custsList}
style={{ padding: 16, borderRadius: 6, background: '#fff', marginTop: 16 }}
pagination={false}
bordered={true}
rowKey={'user_id'}
rowKey={(record) => {
return `${record.cust_id}_${record.user_id}`;
}}
loading={loading}
>
<Table.Column
title="客户"
width={200}
dataIndex={'name'}
render={(value, record: IStaffsItem) => {
render={(value, record: ICustItem) => {
return (
<div
onClick={() => {
setRecord(record);
setOpen(true);
}}
style={{ color: '#1890ff', cursor: 'pointer' }}
style={{ cursor: 'pointer', display: 'flex' }}
>
<span
<div
style={{
display: 'inline-block',
marginRight: record.isleader == 1 ? 4 : 0,
}}
>
{value}
</span>
{record?.isleader == 1 ? (
<span
style={{
color: '#999',
fontSize: 12,
border: '1px solid #ddd',
width: 56,
height: 56,
flexShrink: 0,
borderRadius: 4,
padding: '2px 4px',
overflow: 'hidden',
}}
onClick={(e) => {
e.stopPropagation();
}}
>
<Image width={56} height={56} src={record.avatar}></Image>
</div>
<div style={{ marginLeft: 8 }}>
<div style={{ color: '#1890ff', wordBreak: 'break-all' }}>
{value}[{record.remark}]
</div>
<div style={{ display: 'flex', alignItems: 'center' }}>
<Gender gender={record.gender}></Gender>
<span style={{ marginLeft: 4, color: '#389e0d' }}>
@{CustType[record.type]}
</span>
) : null}
</div>
</div>
</div>
);
}}
/>
<Table.Column title="客户标签" width={160} dataIndex={'position'} />
<Table.Column title="跟进员工" width={160} dataIndex={'position'} />
<Table.Column title="商机阶段" width={160} dataIndex={'position'} />
<Table.Column title="添加方式" width={160} dataIndex={'position'} />
<Table.Column title="添加时间" width={160} dataIndex={'position'} />
<Table.Column title="操作" width={160} dataIndex={'position'} />
<Table.Column
title="客户标签"
width={160}
onCell={() => {
return {
style: {
paddingBottom: 8,
},
};
}}
render={(value) => {
try {
let arr = JSON.parse(value);
if (arr.length) {
return (
<>
{arr.length >= 3 ? (
<Popover
content={() => {
return (
<>
{arr.map((item: any) => {
return (
<Tag
key={`${item?.group_name}${item?.tag_name}`}
color="green"
title={`${item?.group_name}${item?.tag_name}`}
style={{ marginBottom: 4 }}
>
{item?.tag_name}
</Tag>
);
})}
</>
);
}}
>
<Tag
color="green"
title={`${arr[0]?.group_name}${arr[0]?.tag_name}`}
style={{ marginBottom: 4 }}
>
{arr[0]?.tag_name}
</Tag>
{arr[1] ? (
<Tag
color="green"
title={`${arr[1]?.group_name}${arr[1]?.tag_name}`}
style={{ marginBottom: 4 }}
>
{arr[1]?.tag_name}
</Tag>
) : null}
<Tag color="green" style={{ marginBottom: 4 }}>
...
</Tag>
</Popover>
) : (
<>
<Tag
color="green"
title={`${arr[0]?.group_name}${arr[0]?.tag_name}`}
style={{ marginBottom: 4 }}
>
{arr[0]?.tag_name}
</Tag>
{arr[1] ? (
<Tag
color="green"
title={`${arr[1]?.group_name}${arr[1]?.tag_name}`}
style={{ marginBottom: 4 }}
>
{arr[1]?.tag_name}
</Tag>
) : null}
</>
)}
</>
);
}
} catch (e) {}
return <div style={{ marginBottom: 4 }}></div>;
}}
dataIndex={'tags'}
/>
<Table.Column title="跟进员工" width={120} dataIndex={'user_id'} />
{/* <Table.Column title="商机阶段" width={160} dataIndex={'position'} /> */}
<Table.Column
title="添加方式"
width={140}
dataIndex={'add_way'}
render={(value) => {
return <>{AddWay[value]}</>;
}}
/>
<Table.Column title="添加时间" width={140} dataIndex={'create_time'} />
{/* <Table.Column title="操作" width={160} dataIndex={'position'} /> */}
</Table>
<Drawer title="成员详情" open={open} onClose={() => setOpen(false)} width={800} />
<Drawer
title={`${record?.name} 客户详情`}
open={open}
onClose={() => setOpen(false)}
width={800}
>
<div>
<div
style={{
display: 'flex',
borderBottom: '1px solid #ddd',
paddingBottom: 12,
marginBottom: 12,
}}
>
<div className={styles.modalAvatar}>
<img src={record?.avatar} alt="" />
</div>
<div style={{ display: 'flex', flexDirection: 'column' }}>
<div style={{ fontSize: 16 }}>
<span style={{ marginRight: 8 }}>{record?.name}</span>
<Gender gender={record?.gender} />
</div>
<span style={{ marginLeft: 4, color: '#389e0d' }}>
@{record ? CustType[record?.type] : ''}
</span>
<div style={{ color: '#666' }}>{record?.description}</div>
</div>
</div>
<div>{record?.remark}</div>
<div>{record ? AddWay[record?.add_way] : ''}</div>
<div>{record?.user_id}</div>
<div>{record?.create_time}</div>
<div
style={{
paddingTop: 12,
marginBottom: 12,
paddingBottom: 12,
borderBottom: '1px solid #ddd',
fontSize: 16,
fontWeight: 'bold',
}}
>
</div>
{formatTags(record?.tags)}
</div>
</Drawer>
<Pagination
style={{
background: '#fff',
@@ -231,7 +388,7 @@ const CustomList: React.FC = () => {
}}
current={param.curr_page}
pageSize={param.page_count}
total={staffsData.count}
total={count}
pageSizeOptions={[10, 20, 50, 100]}
onShowSizeChange={(current, size) => {
param.page_count = size;

View File

@@ -78,13 +78,15 @@ const DepartmentsList: React.FC = () => {
post({ url: '/Departments/List' }).then((res) => {
setLoadingL(false);
if (res.err_code == 0) {
if (Array.isArray(res.data) && res.data.length) {
if (Array.isArray(res.data)) {
setDepartmentsList(res.data);
if (res.data.length) {
param.dep_id = res.data[0].id;
setDepartmentsID(param.dep_id);
setDepartmentsList(res.data);
getStaffsList();
}
}
}
});
};
@@ -246,7 +248,7 @@ const DepartmentsList: React.FC = () => {
<SearchBarPlugin>
<Form autoComplete="off">
<Row gutter={{ xs: 0, sm: 16 }}>
<Col xs={24} sm={12} md={8}>
<Col xs={24} lg={12} xl={8}>
<Form.Item label={<span style={{ textIndent: '1em' }}></span>}>
<Input
autoComplete="off"
@@ -258,7 +260,7 @@ const DepartmentsList: React.FC = () => {
/>
</Form.Item>
</Col>
<Col xs={24} sm={12} md={8}>
<Col xs={24} lg={12} xl={8}>
<Form.Item label={<span style={{ textIndent: '1em' }}></span>}>
<Input
autoComplete="off"
@@ -270,7 +272,7 @@ const DepartmentsList: React.FC = () => {
/>
</Form.Item>
</Col>
<Col xs={24} sm={12} md={8}>
<Col xs={24} lg={12} xl={8}>
<Form.Item label="手机号">
<Input
autoComplete="off"
@@ -282,20 +284,6 @@ const DepartmentsList: React.FC = () => {
/>
</Form.Item>
</Col>
{/* <Col xs={24} sm={12} md={6}>
<Form.Item label="用户名">
<Select
defaultValue="lucy"
style={{ width: '100%' }}
onChange={() => {}}
options={[
{ value: 'jack', label: 'Jack' },
{ value: 'lucy', label: 'Lucy' },
{ value: 'Yiminghe', label: 'yiminghe' },
]}
/>
</Form.Item>
</Col> */}
</Row>
</Form>
</SearchBarPlugin>

View File

@@ -1,13 +1,6 @@
import Footer from '@/components/Footer';
import { IAjaxReturn, post } from '@/services/ajax';
import {
AlipayCircleOutlined,
LockOutlined,
MobileOutlined,
TaobaoCircleOutlined,
UserOutlined,
WeiboCircleOutlined,
} from '@ant-design/icons';
import { LockOutlined, MobileOutlined, UserOutlined } from '@ant-design/icons';
import {
LoginForm,
ProFormCaptcha,
@@ -15,59 +8,13 @@ import {
ProFormText,
} from '@ant-design/pro-components';
import { useEmotionCss } from '@ant-design/use-emotion-css';
import { FormattedMessage, Helmet, history, SelectLang, useModel } from '@umijs/max';
import { FormattedMessage, Helmet, history, useModel } from '@umijs/max';
import { Alert, App, Tabs } from 'antd';
import { stringify as qsStringify } from 'qs';
import React, { useState } from 'react';
import { flushSync } from 'react-dom';
import Settings from '../../../../config/defaultSettings';
const ActionIcons = () => {
const langClassName = useEmotionCss(({ token }) => {
return {
marginLeft: '8px',
color: 'rgba(0, 0, 0, 0.2)',
fontSize: '24px',
verticalAlign: 'middle',
cursor: 'pointer',
transition: 'color 0.3s',
'&:hover': {
color: token.colorPrimaryActive,
},
};
});
return (
<>
<AlipayCircleOutlined key="AlipayCircleOutlined" className={langClassName} />
<TaobaoCircleOutlined key="TaobaoCircleOutlined" className={langClassName} />
<WeiboCircleOutlined key="WeiboCircleOutlined" className={langClassName} />
</>
);
};
const Lang = () => {
const langClassName = useEmotionCss(({ token }) => {
return {
width: 42,
height: 42,
lineHeight: '42px',
position: 'fixed',
right: 16,
borderRadius: token.borderRadius,
':hover': {
backgroundColor: token.colorBgTextHover,
},
};
});
return (
<div className={langClassName} data-lang>
{SelectLang && <SelectLang />}
</div>
);
};
const LoginMessage: React.FC<{
content: string;
}> = ({ content }) => {
@@ -100,17 +47,6 @@ const Login: React.FC = () => {
};
});
const fetchUserInfo = async () => {
const userInfo = await initialState?.fetchUserInfo?.();
if (userInfo) {
flushSync(() => {
setInitialState((s) => ({
...s,
currentUser: userInfo,
}));
});
}
};
const { notification } = App.useApp();
window.NotificationCF = notification;
@@ -154,24 +90,6 @@ const Login: React.FC = () => {
padding: '32px 0',
}}
>
{/* <ChatTime msgtime={1680713999000}></ChatTime>
<ChatTime msgtime={1680763041000}></ChatTime>
<ChatTime msgtime={1680710399000}></ChatTime>
<ChatTime msgtime={1680623999000}></ChatTime>
<ChatTime msgtime={1680537599000}></ChatTime>
<ChatTime msgtime={1680451199000}></ChatTime>
<ChatTime msgtime={1680331041000}></ChatTime>
<ChatTime msgtime={1680195599000}></ChatTime>
<ChatTime msgtime={1680244641000}></ChatTime>
<ChatTime msgtime={1680191999000}></ChatTime>
<ChatTime msgtime={1680158241000}></ChatTime>
<ChatRevoke></ChatRevoke>
<ChatAgreeOrNot />
<ChatVoice></ChatVoice>
<ChatVideo></ChatVideo>
<ChatCard></ChatCard>
<ChatEmotion></ChatEmotion>
<ChatBar></ChatBar> */}
<LoginForm
contentStyle={{
minWidth: 280,

View File

@@ -1,3 +1,4 @@
import { post } from '@/services/ajax';
import { Area, Line } from '@ant-design/charts';
import { BarChartOutlined, CommentOutlined, TeamOutlined } from '@ant-design/icons';
import { PageContainer } from '@ant-design/pro-components';
@@ -6,31 +7,84 @@ import { DataItemCard } from './components/DataItemCard';
import { DataSumItemCard } from './components/DataSumItemCard';
import styles from './index.module.scss';
const Workbench: React.FC = () => {
const [data, setData] = useState([]);
type ICustChartItem = {
name: string;
num: number;
time: string;
};
const asyncFetch = () => {
fetch('https://gw.alipayobjects.com/os/bmw-prod/e00d52f4-2fa6-47ee-a0d7-105dd95bde20.json')
.then((response) => response.json())
.then((json) => setData(json))
.catch((error) => {
console.log('fetch data failed', error);
type IData = {
overView: {
custs_total: number;
groups_members_total: number;
groups_total: number;
};
custsInfo: {
month_custs: number;
today_custs: number;
today_loss: number;
today_net_growth: number;
};
groupsInfo: {
today_diss_groups: number;
today_diss_groups_members: number;
today_groups: number;
today_groups_members: number;
};
custsChart: ICustChartItem[];
groupsChart: ICustChartItem[];
};
const Workbench: React.FC = () => {
const [data, setData] = useState<IData>({
overView: {
custs_total: 0,
groups_members_total: 0,
groups_total: 0,
},
custsInfo: {
month_custs: 0,
today_custs: 0,
today_loss: 0,
today_net_growth: 0,
},
groupsInfo: {
today_diss_groups: 0,
today_diss_groups_members: 0,
today_groups: 0,
today_groups_members: 0,
},
custsChart: [],
groupsChart: [],
});
const getWorkBenchInfo = () => {
post({ url: '/WorkBench/Info' }).then((res) => {
if (res.err_code == 0) {
if (res.over_view) {
data.overView = res.over_view;
}
if (res.groups_info) {
data.groupsInfo = res.groups_info;
}
if (res.custs_info) {
data.custsInfo = res.custs_info;
}
if (Array.isArray(res.custs_chart)) {
data.custsChart = res.custs_chart;
}
if (Array.isArray(res.groups_chart)) {
data.groupsChart = res.groups_chart;
}
setData({ ...data });
}
});
};
useEffect(() => {
asyncFetch();
getWorkBenchInfo();
}, []);
const [dataArea, setDataArea] = useState([
{ type: '订单数', date: '2021-02-01', value: 400 },
{ type: '订单数', date: '2021-02-05', value: 900 },
{ type: '订单数', date: '2021-02-08', value: 300 },
{ type: '收衣数', date: '2021-02-01', value: 700 },
{ type: '收衣数', date: '2021-02-05', value: 500 },
{ type: '收衣数', date: '2021-02-08', value: 1000 },
]);
return (
<PageContainer>
<div className={styles.dataSum} style={{ padding: '24px 0' }}>
@@ -42,67 +96,72 @@ const Workbench: React.FC = () => {
padding: '0 24px',
}}
>
<span style={{ fontSize: 16 }}></span>
<span style={{ color: '#999' }}>2022-12-12 23:30:30</span>
<span style={{ fontSize: 18 }}></span>
{/* <span style={{ color: '#999' }}>更新时间2022-12-12 23:30:30</span> */}
</div>
<div style={{ display: 'flex' }}>
<DataSumItemCard
title="客户数量"
content="当前员工权限范围内的全部客户数量(含重复)"
icon={<TeamOutlined className={styles.icon} />}
count={111}
count={data.overView.custs_total}
/>
<DataSumItemCard
title="客群数量"
content="当前员工权限范围内的全部客群数量"
icon={<CommentOutlined className={styles.icon} />}
count={111}
count={data.overView.groups_total}
/>
<DataSumItemCard
title="客群成员总数"
content="当前员工权限范围内客群成员的总数(含员工)(含重复)"
icon={<BarChartOutlined className={styles.icon} />}
count={111}
count={data.overView.groups_members_total}
/>
</div>
</div>
<div className={styles.dataSum}>
<div style={{ fontSize: 16 }}></div>
<div style={{ fontSize: 18 }}></div>
<div className={styles.dataCardBox}>
<DataItemCard
title="今日新增客户"
content="当前员工权限范围内今日添加的客户数(含重复及流失)"
count={11}
count={data.custsInfo.today_custs}
/>
<span style={{ width: 16 }} />
<DataItemCard
{/* <DataItemCard
title="今日跟进客户"
content="当前员工权限范围内今日处于跟进中状态的客户数(含重复)"
count={11}
/>
<span style={{ width: 16 }} />
/> */}
{/* <span style={{ width: 16 }} /> */}
<DataItemCard
title="今日净增客户"
content="当前员工权限范围内今日添加的客户数(不含重复及流失)"
count={11}
count={data.custsInfo.today_net_growth}
/>
<span style={{ width: 16 }} />
<DataItemCard
title="今日流失客户"
content="当前员工权限范围内的流失的全部客户数量"
count={11}
count={data.custsInfo.today_loss}
/>
<span style={{ width: 16 }} />
<DataItemCard
title="本月新增客户"
content="当前员工权限范围内本月添加的客户数(含重复及流失)"
count={data.custsInfo.month_custs}
/>
{/* <DataItemCard
title="昨日发送申请"
content="当前员工数权限范围内主动向客户发起的申请数"
count={11}
/>
/> */}
</div>
<Line
data={data}
xField="year"
yField="gdp"
data={data.custsChart}
xField="time"
yField="num"
seriesField="name"
// yAxis= {{
// label: {
@@ -123,37 +182,37 @@ const Workbench: React.FC = () => {
/>
</div>
<div className={styles.dataSum}>
<div style={{ fontSize: 16 }}></div>
<div style={{ fontSize: 18 }}></div>
<div className={styles.dataCardBox}>
<DataItemCard
title="今日新增客群"
content="当前员工权限范围内今日创建的客群数"
count={11}
count={data.groupsInfo.today_groups}
/>
<span style={{ width: 16 }} />
<DataItemCard
title="今日解散客群"
content="当前员工权限范围内今日解散的客群数"
count={11}
count={data.groupsInfo.today_diss_groups}
/>
<span style={{ width: 16 }} />
<DataItemCard
title="今日新增成员"
content="当前员工权限范围内今日新增客群成员数(含员工)"
count={11}
count={data.groupsInfo.today_groups_members}
/>
<span style={{ width: 16 }} />
<DataItemCard
title="今日退出成员"
content="当前员工权限范围内今日退出客群成员数(含员工)"
count={11}
count={data.groupsInfo.today_diss_groups_members}
/>
</div>
<Area
data={dataArea}
xField="date"
yField="value"
seriesField="type"
data={data.groupsChart}
xField="time"
yField="num"
seriesField="name"
smooth={true}
legend={{ position: 'top' }}
isStack={false}

31
src/services/config.ts Normal file
View File

@@ -0,0 +1,31 @@
/**
* 添加客户的来源
*/
export const AddWay: any = {
0: '未知来源',
1: '扫描二维码',
2: '搜索手机号',
3: '名片分享',
4: '群聊',
5: '手机通讯录',
6: '微信联系人',
8: '安装第三方应用时自动添加的客服人员',
9: '搜索邮箱',
10: '视频号添加',
11: '通过日程参与人添加',
12: '通过会议参与人添加',
13: '添加微信好友对应的企业微信',
14: '通过智慧硬件专属客服添加',
15: '通过上门服务客服添加',
16: '通过获客链接添加',
201: '内部成员共享',
202: '管理员/负责人分配',
};
/**
* 外部联系人的类型
*/
export const CustType: any = {
1: '微信',
2: '企业微信',
};