From bc8bb916ee5c366eb590bdd55bf0b1f0176ef66a Mon Sep 17 00:00:00 2001 From: zhengw <247276359@qq.com> Date: Mon, 17 Apr 2023 17:47:31 +0800 Subject: [PATCH] =?UTF-8?q?=E5=BC=80=E5=8F=91:=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E5=8F=8A=E4=BF=AE=E6=94=B9=E8=B7=AF=E7=94=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/routes.ts | 73 ++--- package.json | 2 + src/pages/ChatLogs/ChatLogsType.ts | 2 +- src/pages/ChatLogs/ChatUtils.tsx | 34 +++ src/pages/ChatLogs/index.tsx | 165 ++++++------ src/pages/CustomList/index.module.scss | 0 src/pages/CustomList/index.tsx | 252 ++++++++++++++++++ src/pages/DepartmentsList/index.tsx | 57 ++-- .../Workbench/components/DataItemCard.tsx | 27 ++ .../Workbench/components/DataSumItemCard.tsx | 30 +++ src/pages/Workbench/index.module.scss | 48 ++++ src/pages/Workbench/index.tsx | 166 ++++++++++++ 12 files changed, 711 insertions(+), 145 deletions(-) create mode 100644 src/pages/CustomList/index.module.scss create mode 100644 src/pages/CustomList/index.tsx create mode 100644 src/pages/Workbench/components/DataItemCard.tsx create mode 100644 src/pages/Workbench/components/DataSumItemCard.tsx create mode 100644 src/pages/Workbench/index.module.scss create mode 100644 src/pages/Workbench/index.tsx diff --git a/config/routes.ts b/config/routes.ts index 823e3f4..0df567e 100644 --- a/config/routes.ts +++ b/config/routes.ts @@ -29,58 +29,69 @@ export default [ // component: './Welcome', // }, { - path: '/departments', + path: '/scrm', name: 'scrm', icon: 'crown', // access: 'canAdmin', routes: [ { - path: '/departments', - redirect: '/departments/page/list', + path: '/scrm', + redirect: '/scrm/custom/workbench', }, { - path: '/departments/page', - name: '部门管理', - // hideInBreadcrumb: true, - // component: './Admin', + path: '/scrm/custom', + name: '客户管理', routes: [ { - path: '/departments/page', - redirect: '/departments/page/list', + path: '/scrm/custom', + redirect: '/scrm/custom/workbench', + }, + { + name: '工作台', + icon: 'table', + path: '/scrm/custom/workbench', + component: './Workbench', + }, + { + name: '客户列表', + icon: 'table', + path: '/scrm/custom/list', + component: './CustomList', + }, + ], + }, + { + path: '/scrm/dep', + name: '部门管理', + routes: [ + { + path: '/scrm/dep', + redirect: '/scrm/dep/list', }, { name: '部门员工', icon: 'table', - path: '/departments/page/list', + path: '/scrm/dep/list', component: './DepartmentsList', }, + ], + }, + { + path: '/scrm/chat', + name: '聊天记录', + routes: [ + { + path: '/scrm/chat', + redirect: '/scrm/chat/list', + }, { name: '成员聊天', icon: 'table', - path: '/departments/page/list2', - component: './ChatLogs', - }, - { - name: '客户聊天', - icon: 'table', - path: '/departments/page/list3', + path: '/scrm/chat/list', component: './ChatLogs', }, ], }, - // { - // path: '/departments/sub-page2', - // name: '商品', - // // component: './TableList', - // routes: [ - // { - // name: '列表', - // icon: 'table', - // path: '/departments/sub-page2/list', - // component: './TableList', - // }, - // ], - // }, ], }, @@ -92,7 +103,7 @@ export default [ // }, { path: '/', - redirect: '/departments', + redirect: '/scrm', }, { path: '*', diff --git a/package.json b/package.json index e91c1df..35229b1 100644 --- a/package.json +++ b/package.json @@ -45,6 +45,7 @@ "not ie <= 10" ], "dependencies": { + "@ant-design/charts": "^1.4.2", "@ant-design/icons": "^5.0.1", "@ant-design/pro-components": "^2.3.57", "@ant-design/use-emotion-css": "1.0.4", @@ -57,6 +58,7 @@ "rc-menu": "^9.8.2", "rc-util": "^5.27.2", "react": "^18.2.0", + "react-countup": "^6.4.2", "react-dev-inspector": "^1.8.4", "react-dom": "^18.2.0", "react-helmet-async": "^1.3.0" diff --git a/src/pages/ChatLogs/ChatLogsType.ts b/src/pages/ChatLogs/ChatLogsType.ts index 675186b..14883fd 100644 --- a/src/pages/ChatLogs/ChatLogsType.ts +++ b/src/pages/ChatLogs/ChatLogsType.ts @@ -106,7 +106,7 @@ export interface IChat { } export interface IChatItem { from?: IStaffsItem; - to?: ICustFollow; + to?: ICustFollow | IStaffsItem | IGroup; group?: any; chat?: IChat; } diff --git a/src/pages/ChatLogs/ChatUtils.tsx b/src/pages/ChatLogs/ChatUtils.tsx index 6a193c4..dfd22b6 100644 --- a/src/pages/ChatLogs/ChatUtils.tsx +++ b/src/pages/ChatLogs/ChatUtils.tsx @@ -5,6 +5,8 @@ * @returns */ +import React, { useEffect, useState } from 'react'; + export const groupMembersCount = (data: any[], state: any) => { let count = 0; data.forEach((item) => { @@ -86,3 +88,35 @@ export const formatTags = (data: any) => { } return <>; }; + +type IGroupIcon = { + groupList: any[]; +}; +/** + * todo 群头像拼接 + * @param props + * @returns + */ +export const GroupIcon: React.FC = (props) => { + const [list, setList] = useState([[], [], []]); + + useEffect(() => { + let temp: any = [[], [], []]; + const { groupList } = props; + for (let index = 0; index < 9; index++) { + const element = groupList[index]; + + if (index < 3) { + temp[0].push(element); + } else if (index < 6) { + temp[1].push(element); + } else { + temp[2].push(element); + } + } + console.log(temp); + }, [props.groupList]); + + //
{item.name ? item.name[0] : '群'}
; + return
; +}; diff --git a/src/pages/ChatLogs/index.tsx b/src/pages/ChatLogs/index.tsx index 417d21f..421a9ea 100644 --- a/src/pages/ChatLogs/index.tsx +++ b/src/pages/ChatLogs/index.tsx @@ -12,11 +12,7 @@ import { ChatBar } from './components/ChatBar'; import { ChatTime } from './components/ChatTime'; import { Gender } from './components/Gender'; import styles from './index.module.scss'; -interface ISearchWord { - '0': string; - '1': string; - '2': string; -} + const ChatLogs: React.FC = () => { const [param] = useState({ curr_page: 1, @@ -80,7 +76,7 @@ const ChatLogs: React.FC = () => { '3': '离职继承完成', }; - const [searchWord, setSearchWord] = useState({ + const [searchWord, setSearchWord] = useState({ '0': '', '1': '', '2': '', @@ -100,72 +96,6 @@ const ChatLogs: React.FC = () => { setFlolowsBox(false); } - // 监听DOM变动 - const callback = function (mutationsList: any) { - // Use traditional 'for loops' for IE 11 - for (let mutation of mutationsList) { - if (mutation.type === 'childList') { - document.querySelector('.curr_page' + param.curr_page)?.scrollIntoView(true); - } else if (mutation.type === 'attributes') { - console.log('The ' + mutation.attributeName + ' attribute was modified.'); - } - } - }; - const observer = new MutationObserver(callback); - - useEffect(() => { - document.addEventListener('click', show, false); - getStaffsList(); - - observer.observe(chatBoxRef.current, { childList: true }); - const myScript = document.createElement('script'); - myScript.src = '/public/scripts/amrnb.js'; - myScript.async = false; - document.body.appendChild(myScript); - - return () => { - document.removeEventListener('click', show, false); - observer.disconnect(); - document.body.removeChild(myScript); - }; - }, []); - - // 获取员工 - const getStaffsList = () => { - post({ url: '/Staffs/Data' }).then((res) => { - if (res.err_code == 0) { - if (Array.isArray(res.data) && res.data.length) { - // setSelectStaff(res.data[0]); - // selectStaffRef.current = res.data[0]; - res.data.forEach((element: IStaffsItem) => { - if (element.user_id == 'yangxb') { - setSelectStaff(element); - selectStaffRef.current = element; - } - }); - setStaffsList(res.data); - setInnerStaffsList(res.data); - getCustFollowsList(); - getGroupList(); - } - } - }); - }; - - const page = (curr: number) => { - param.curr_page = curr; - param.msg_from = selectStaffRef.current?.user_id + ''; - if (tabKey == '0') { - param.msg_to_list = selectInnerStaffRef.current?.user_id + ''; - } else if (tabKey == '1') { - param.msg_to_list = selectCustFollowRef.current?.cust_id + ''; - } else { - param.room_id = selectGroupRef.current?.group_id + ''; - } - timeShowRef.current = false; - getChatLogsList(); - }; - const getChatLogsList = () => { chatLogLoadingRef.current = true; setChatLogLoading(true); @@ -216,6 +146,20 @@ const ChatLogs: React.FC = () => { }); }; + const page = (curr: number) => { + param.curr_page = curr; + param.msg_from = selectStaffRef.current?.user_id + ''; + if (tabKey == '0') { + param.msg_to_list = selectInnerStaffRef.current?.user_id + ''; + } else if (tabKey == '1') { + param.msg_to_list = selectCustFollowRef.current?.cust_id + ''; + } else { + param.room_id = selectGroupRef.current?.group_id + ''; + } + timeShowRef.current = false; + getChatLogsList(); + }; + const getGroupList = () => { post({ url: '/Groups/GroupsList', @@ -271,6 +215,58 @@ const ChatLogs: React.FC = () => { }); }; + // 获取员工 + const getStaffsList = () => { + post({ url: '/Staffs/Data' }).then((res) => { + if (res.err_code == 0) { + if (Array.isArray(res.data) && res.data.length) { + setSelectStaff(res.data[0]); + selectStaffRef.current = res.data[0]; + // res.data.forEach((element: IStaffsItem) => { + // if (element.user_id == 'yangxb') { + // setSelectStaff(element); + // selectStaffRef.current = element; + // } + // }); + setStaffsList(res.data); + setInnerStaffsList(res.data); + getCustFollowsList(); + getGroupList(); + } + } + }); + }; + + // 监听DOM变动 + const callback = function (mutationsList: any) { + // Use traditional 'for loops' for IE 11 + for (let mutation of mutationsList) { + if (mutation.type === 'childList') { + document.querySelector('.curr_page' + param.curr_page)?.scrollIntoView(true); + } else if (mutation.type === 'attributes') { + console.log('The ' + mutation.attributeName + ' attribute was modified.'); + } + } + }; + const observer = new MutationObserver(callback); + + useEffect(() => { + document.addEventListener('click', show, false); + getStaffsList(); + + observer.observe(chatBoxRef.current, { childList: true }); + const myScript = document.createElement('script'); + myScript.src = '/public/scripts/amrnb.js'; + myScript.async = false; + document.body.appendChild(myScript); + + return () => { + document.removeEventListener('click', show, false); + observer.disconnect(); + document.body.removeChild(myScript); + }; + }, []); + // const { notification } = App.useApp(); const tabContent = () => { if (tabKey == '0') { @@ -549,7 +545,7 @@ const ChatLogs: React.FC = () => {
{ + onClick={() => { setSelectCustFollow(undefined); selectCustFollowRef.current = undefined; setSelectInnerStaff(undefined); @@ -637,7 +633,7 @@ const ChatLogs: React.FC = () => { setSearchWord({ ...searchWord }); }} allowClear - > + /> { onChange={(val) => { setTabKey(val); }} - > + />
{tabContent()}
@@ -688,9 +684,7 @@ const ChatLogs: React.FC = () => { footer={false} > {tabKeyRef.current == '0' ? ( - + ) : tabKeyRef.current == '1' ? (
{
{selectCustFollow?.name} - +
{selectCustFollow?.description}
@@ -718,7 +712,8 @@ const ChatLogs: React.FC = () => { ) : (
- 群主:{groupMembersObjRef.current[selectGroupRef.current?.owner]?.name} + 群主: + {groupMembersObjRef.current[selectGroupRef.current?.owner as string]?.name}
{adminList(selectGroupRef.current?.admin_list, groupMembersObjRef.current)} @@ -937,26 +932,26 @@ const ChatLogs: React.FC = () => { 没有更多聊天记录了
) : null} - {chatLogs.map((item, i) => { + {chatLogs.map((item) => { if (item.curr_page) { return (
+ /> ); } else { return (
{/* {item.show_time ? : null} */} - + {tabKey == '2' ? ( + /> ) : ( { : selectCustFollowRef.current } chat={item} - > + /> )}
); diff --git a/src/pages/CustomList/index.module.scss b/src/pages/CustomList/index.module.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/pages/CustomList/index.tsx b/src/pages/CustomList/index.tsx new file mode 100644 index 0000000..886ddc0 --- /dev/null +++ b/src/pages/CustomList/index.tsx @@ -0,0 +1,252 @@ +import { SearchBarPlugin, SearchBottonsCardPlugin } from '@/components/SearchBarPlugin'; +import { post } from '@/services/ajax'; +import { PageContainer } from '@ant-design/pro-components'; +import { Button, Col, DatePicker, Drawer, Form, Input, Pagination, Row, Table } from 'antd'; +import { stringify } from 'qs'; +import React, { useEffect, useState } from 'react'; +import { IStaffsItem } from '../ChatLogs/ChatLogsType'; + +interface IDepartment { + children: null | IDepartment[]; + department_leader: string; + id: number; + name: string; + parent_id: number; + sort: number; +} + +interface IStaffsData { + count: number; + data?: IStaffsItem[]; +} + +type Param = { + curr_page: number; + page_count: number; + dep_id: number; + name?: string; + position?: string; + telephone?: string; + mobile?: string; +}; + +const CustomList: React.FC = () => { + const [param] = useState({ + curr_page: 1, + page_count: 20, + dep_id: 0, + }); + + const [departmentID, setDepartmentsID] = useState(0); + const [departmentsList, setDepartmentsList] = useState([]); + const [staffsData, setStaffsData] = useState({ count: 0, data: [] }); + const [loadingL, setLoadingL] = useState(false); + const [loading, setLoading] = useState(false); + const [open, setOpen] = useState(false); + const [record, setRecord] = useState(); + + const getStaffsList = () => { + setLoading(true); + post({ url: '/Staffs/List', 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(); + } + } + }); + }; + + const page = (page: number) => { + param.curr_page = page; + getStaffsList(); + }; + + useEffect(() => { + getDepartmentsList(); + }, []); + + return ( + +
+ +
+ + + + { + param.name = e.target.value.trim(); + }} + allowClear + onPressEnter={() => page(1)} + /> + + + + 职务}> + { + param.position = e.target.value.trim(); + }} + allowClear + onPressEnter={() => page(1)} + /> + + + + 手机号}> + { + param.mobile = e.target.value.trim(); + }} + allowClear + onPressEnter={() => page(1)} + /> + + + + 手机号}> + { + console.log(dates, dateStrings); + }} + /> + + + {/* + + { @@ -254,11 +255,11 @@ const DepartmentsList: React.FC = () => { }} allowClear onPressEnter={() => page(1)} - > + /> - + 职务}> { @@ -266,7 +267,7 @@ const DepartmentsList: React.FC = () => { }} allowClear onPressEnter={() => page(1)} - > + /> @@ -278,7 +279,7 @@ const DepartmentsList: React.FC = () => { }} allowClear onPressEnter={() => page(1)} - > + /> {/* @@ -374,20 +375,20 @@ const DepartmentsList: React.FC = () => {
); }} - > - + /> + { return <>{val.join(',')}; }} - > - - + /> + + setOpen(false)} width={800}> - + { // setParam({ ...param }); page(1); }} - showTotal={(total, range) => { + showTotal={(total) => { return 共{total}条; }} - onChange={(curr, pageSize) => { + onChange={(curr) => { page(curr); }} /> diff --git a/src/pages/Workbench/components/DataItemCard.tsx b/src/pages/Workbench/components/DataItemCard.tsx new file mode 100644 index 0000000..f387e64 --- /dev/null +++ b/src/pages/Workbench/components/DataItemCard.tsx @@ -0,0 +1,27 @@ +import { ExclamationCircleOutlined } from '@ant-design/icons'; +import { Popover } from 'antd'; +import React from 'react'; +import CountUp from 'react-countup'; +import styles from '../index.module.scss'; + +type IProps = { + title: string; + content: string; + count: number; +}; + +export const DataItemCard: React.FC = (props) => { + return ( +
+
+ {props.title} + + + +
+
+ +
+
+ ); +}; diff --git a/src/pages/Workbench/components/DataSumItemCard.tsx b/src/pages/Workbench/components/DataSumItemCard.tsx new file mode 100644 index 0000000..8e1deb5 --- /dev/null +++ b/src/pages/Workbench/components/DataSumItemCard.tsx @@ -0,0 +1,30 @@ +import { ExclamationCircleOutlined } from '@ant-design/icons'; +import { Popover } from 'antd'; +import React from 'react'; +import CountUp from 'react-countup'; +import styles from '../index.module.scss'; +type IProps = { + title: string; + content: string; + count: number; + icon: React.ReactNode; +}; + +export const DataSumItemCard: React.FC = (props) => { + return ( +
+
{props.icon}
+
+
+ {props.title} + + + +
+
+ +
+
+
+ ); +}; diff --git a/src/pages/Workbench/index.module.scss b/src/pages/Workbench/index.module.scss new file mode 100644 index 0000000..6a2ec64 --- /dev/null +++ b/src/pages/Workbench/index.module.scss @@ -0,0 +1,48 @@ +.dataSum { + margin-bottom: 24px; + padding: 24px; + color: #000; + background-color: #fff; + border-radius: 8px; +} + +.dataItem { + display: inline-flex; + flex: 1; + margin-bottom: 12px; + border-right: 1px solid #ddd; + padding-left: 24px; +} + +.dataIconBox { + display: flex; + align-items: center; + justify-content: center; + width: 64px; + height: 64px; + margin-right: 16px; + background-color: #edf2f9; + border-radius: 12px; + + .icon { + color: #1890ff; + font-size: 32px; + } +} + +.dataCount { + font-size: 24px; +} + +.dataCardBox { + display: flex; + margin-top: 16px; + margin-bottom: 16px; +} + +.dataCard { + padding: 16px; + border: 1px solid #ddd; + border-radius: 12px; + flex: 1; +} diff --git a/src/pages/Workbench/index.tsx b/src/pages/Workbench/index.tsx new file mode 100644 index 0000000..97d4544 --- /dev/null +++ b/src/pages/Workbench/index.tsx @@ -0,0 +1,166 @@ +import { Area, Line } from '@ant-design/charts'; +import { BarChartOutlined, CommentOutlined, TeamOutlined } from '@ant-design/icons'; +import { PageContainer } from '@ant-design/pro-components'; +import React, { useEffect, useState } from 'react'; +import { DataItemCard } from './components/DataItemCard'; +import { DataSumItemCard } from './components/DataSumItemCard'; +import styles from './index.module.scss'; + +const Workbench: React.FC = () => { + const [data, setData] = useState([]); + + 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); + }); + }; + + useEffect(() => { + asyncFetch(); + }, []); + + 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 ( + +
+
+ 数据总览 + 更新时间:2022-12-12 23:30:30 +
+
+ } + count={111} + /> + } + count={111} + /> + } + count={111} + /> +
+
+
+
客户数据
+
+ + + + + + + + + +
+ `${(v / 10e8).toFixed(1)} B`, + // }, + // },} + legend={{ + position: 'top', + }} + smooth={true} + // @TODO 后续会换一种动画方式 + animation={{ + appear: { + animation: 'path-in', + duration: 3000, + }, + }} + /> +
+
+
客群数据
+
+ + + + + + + +
+ +
+
+ ); +}; + +export default Workbench;