diff --git a/config/config.ts b/config/config.ts index 960a7f1..6c7eceb 100644 --- a/config/config.ts +++ b/config/config.ts @@ -136,6 +136,7 @@ export default defineConfig({ headScripts: [ // 解决首次加载时白屏的问题 { src: '/scripts/loading.js', async: true }, + { src: '/scripts/amrnb.js', async: true }, ], //================ pro 插件配置 ================= presets: ['umi-presets-pro'], diff --git a/src/pages/ChatLogs/ChatLogsType.ts b/src/pages/ChatLogs/ChatLogsType.ts index 37002a6..4b9511f 100644 --- a/src/pages/ChatLogs/ChatLogsType.ts +++ b/src/pages/ChatLogs/ChatLogsType.ts @@ -54,10 +54,17 @@ export interface ICustFollow { state: number; sync_time: string; tags: string; + + add_way: number; + + create_time: string; + + user_id: string; } export interface IGroup { admin_list: string; + adminUserIDs: string[]; create_time: string; group_id: string; name: string; diff --git a/src/pages/ChatLogs/ChatUtils.tsx b/src/pages/ChatLogs/ChatUtils.tsx index e7e286c..0bca79d 100644 --- a/src/pages/ChatLogs/ChatUtils.tsx +++ b/src/pages/ChatLogs/ChatUtils.tsx @@ -60,6 +60,27 @@ export const adminList = (data: any, groupMembers: any) => { return <>; }; +/** + * 返回群管理员 userid 数组 + * @param data + * @returns + */ +export const getAdminList = (data: any) => { + if (data) { + try { + const msg = JSON.parse(data); + if (Array.isArray(msg)) { + let arr: string[] = []; + msg.forEach((item) => { + arr.push(item.userid); + }); + return arr; + } + } catch (e) {} + } + + return []; +}; /** * 客户等级等信息 diff --git a/src/pages/ChatLogs/components/Gender.tsx b/src/pages/ChatLogs/components/Gender.tsx index 20bfaeb..a0dbb82 100644 --- a/src/pages/ChatLogs/components/Gender.tsx +++ b/src/pages/ChatLogs/components/Gender.tsx @@ -7,28 +7,34 @@ export const Gender: React.FC = (props) => { {props?.gender ? ( <> {props?.gender == 1 ? ( - - - + + + + + ) : ( - - - + + + + + )} ) : ( - - - + + + + + )} ); diff --git a/src/pages/ChatLogs/components/Svgs.tsx b/src/pages/ChatLogs/components/Svgs.tsx new file mode 100644 index 0000000..4a08287 --- /dev/null +++ b/src/pages/ChatLogs/components/Svgs.tsx @@ -0,0 +1,43 @@ +export const OwnerSvg = () => { + return ( + + + + + + ); +}; + +export const AdminSvg = () => { + return ( + + + + + + ); +}; diff --git a/src/pages/ChatLogs/index.module.scss b/src/pages/ChatLogs/index.module.scss index 1d41167..25307c4 100644 --- a/src/pages/ChatLogs/index.module.scss +++ b/src/pages/ChatLogs/index.module.scss @@ -66,6 +66,19 @@ border-radius: 4px; } +.inGroupAvatar { + position: relative; + display: flex; + flex-shrink: 0; + align-items: center; + justify-content: center; + width: 56px; + height: 56px; + line-height: 1; + background-color: #69b1ff; + border-radius: 4px; +} + .chatBBox { position: relative; height: calc(100vh - 212px - 164px); @@ -82,8 +95,8 @@ transition: top 0.3s, height 0.3s; &.delFollowListShow { - top: 0; - height: calc(100% - 34px); + top: 164px; + height: calc(100% - 164px); } } diff --git a/src/pages/ChatLogs/index.tsx b/src/pages/ChatLogs/index.tsx index 3e4bdf6..e248aeb 100644 --- a/src/pages/ChatLogs/index.tsx +++ b/src/pages/ChatLogs/index.tsx @@ -5,12 +5,13 @@ import { Drawer, Form, Input, Tabs } from 'antd'; import Spin from 'antd/lib/spin'; import { stringify } from 'qs'; import React, { useEffect, useRef, useState } from 'react'; +import { CustDetailContent } from '../CustomList/components/CustDetailContent'; import { DepartmentMembersDetail } from '../DepartmentsList/components/DepartmentMemberDetail'; import { IChat, ICustFollow, IGroup, IGroupMembers, IStaffsItem } from './ChatLogsType'; -import { adminList, formatTags, groupMembersCount, groupMembersCount2 } from './ChatUtils'; +import { adminList, getAdminList, groupMembersCount, groupMembersCount2 } from './ChatUtils'; import { ChatBar } from './components/ChatBar'; import { ChatTime } from './components/ChatTime'; -import { Gender } from './components/Gender'; +import { AdminSvg, OwnerSvg } from './components/Svgs'; import styles from './index.module.scss'; const ChatLogs: React.FC = () => { @@ -187,11 +188,22 @@ const ChatLogs: React.FC = () => { if (res.err_code == 0) { if (Array.isArray(res.data)) { groupMembersObjRef.current = {}; + let owner: IGroupMembers[] = []; + let admin_list: IGroupMembers[] = []; + let other: IGroupMembers[] = []; res.data.forEach((item: IGroupMembers) => { item.avatar = item.staff_avatar || item.avatar; groupMembersObjRef.current[item.user_id] = item; + if (item.user_id == selectGroupRef.current?.owner) { + owner.push(item); + } else if (selectGroupRef.current?.adminUserIDs.includes(item.user_id)) { + admin_list.push(item); + } else { + other.push(item); + } }); - setGroupMembersList(res.data); + // 对群员 创建者 > 管理员 > 普通成员 排序 + setGroupMembersList([...owner, ...admin_list, ...other]); page(1); } } @@ -256,18 +268,79 @@ const ChatLogs: React.FC = () => { 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); }; }, []); + // 外部联系人Item + const custFollowsListItem = (item: ICustFollow) => { + return ( +
{ + tabKeyRef.current = tabKey; + + setSelectInnerStaff(undefined); + selectInnerStaffRef.current = undefined; + setSelectGroup(undefined); + selectGroupRef.current = undefined; + + setSelectCustFollow(item); + selectCustFollowRef.current = item; + page(1); + }} + style={{ display: item.name.includes(searchWord['1']) ? '' : 'none' }} + > +
+ +
+
+
+ {item.name} +
+
{item.remark}
+
+
+ ); + }; + + // 客户群聊列表项 + const groupListItem = (item: IGroup) => { + return ( +
{ + tabKeyRef.current = tabKey; + setSelectCustFollow(undefined); + selectCustFollowRef.current = undefined; + setSelectInnerStaff(undefined); + selectInnerStaffRef.current = undefined; + setSelectGroup(item); + selectGroupRef.current = item; + selectGroupRef.current.adminUserIDs = getAdminList(item.admin_list); + + getGroupMembersList(); + }} + style={{ display: item.name.includes(searchWord['2']) ? '' : 'none' }} + > +
{item.name ? item.name[0] : '群'}
+
+
+ {item.name || '未定义群名'} +
+
{groupStatus[item.status]}
+
+
+ ); + }; + // const { notification } = App.useApp(); const tabContent = () => { if (tabKey == '0') { @@ -282,9 +355,7 @@ const ChatLogs: React.FC = () => { return (
{ tabKeyRef.current = tabKey; @@ -324,9 +395,7 @@ const ChatLogs: React.FC = () => { ); }) ) : ( -
- 暂无内部联系人 -
+
暂无内部联系人
)} ); @@ -335,53 +404,12 @@ const ChatLogs: React.FC = () => { <> {custFollowsList.length ? ( custFollowsList.map((item) => { - if (item.state == 0) return null; - return ( -
{ - tabKeyRef.current = tabKey; - - setSelectInnerStaff(undefined); - selectInnerStaffRef.current = undefined; - setSelectGroup(undefined); - selectGroupRef.current = undefined; - - setSelectCustFollow(item); - selectCustFollowRef.current = item; - page(1); - }} - style={{ display: item.name.includes(searchWord['1']) ? '' : 'none' }} - > -
- -
-
-
- {item.name} -
-
{item.remark}
-
-
- ); + return item.state == 0 ? null : custFollowsListItem(item); }) ) : ( -
- 暂无外部联系人 -
+
暂无外部联系人
)} -
+
{ @@ -391,51 +419,9 @@ const ChatLogs: React.FC = () => { 已删联系人 {delFollowListShow ? : }
-
+
{custFollowsList.map((item) => { - if (item.state == 1) return null; - return ( -
{ - tabKeyRef.current = tabKey; - - setSelectInnerStaff(undefined); - selectInnerStaffRef.current = undefined; - setSelectGroup(undefined); - selectGroupRef.current = undefined; - - setSelectCustFollow(item); - selectCustFollowRef.current = item; - page(1); - }} - style={{ display: item.name.includes(searchWord['1']) ? '' : 'none' }} - > -
- -
-
-
- {item.name} -
-
{item.remark}
-
-
- ); + return item.state == 1 ? null : custFollowsListItem(item); })}
@@ -446,45 +432,12 @@ const ChatLogs: React.FC = () => { <> {groupList.length ? ( groupList.map((item) => { - if (item.state == 0) return null; - return ( -
{ - tabKeyRef.current = tabKey; - setSelectCustFollow(undefined); - selectCustFollowRef.current = undefined; - setSelectInnerStaff(undefined); - selectInnerStaffRef.current = undefined; - setSelectGroup(item); - selectGroupRef.current = item; - getGroupMembersList(); - }} - style={{ display: item.name.includes(searchWord['2']) ? '' : 'none' }} - > -
{item.name ? item.name[0] : '群'}
-
-
- {item.name || '未定义群名'} -
-
{groupStatus[item.status]}
-
-
- ); + return item.state == 0 ? null : groupListItem(item); }) ) : ( -
- 暂无客户群聊 -
+
暂无客户群聊
)} -
+
{ @@ -494,40 +447,9 @@ const ChatLogs: React.FC = () => { 已解散的群 {delGroupListShow ? : }
-
+
{groupList.map((item) => { - if (item.state == 1) return null; - return ( -
{ - tabKeyRef.current = tabKey; - setSelectCustFollow(undefined); - selectCustFollowRef.current = undefined; - setSelectInnerStaff(undefined); - selectInnerStaffRef.current = undefined; - setSelectGroup(item); - selectGroupRef.current = item; - getGroupMembersList(); - }} - style={{ display: item.name.includes(searchWord['2']) ? '' : 'none' }} - > -
{item.name ? item.name[0] : '群'}
-
-
- {item.name || '未定义群名'} -
-
{groupStatus[item.status]}
-
-
- ); + return item.state == 1 ? null : groupListItem(item); })}
@@ -536,6 +458,104 @@ const ChatLogs: React.FC = () => { } }; + // 删除的联系人/群 + const tabContentDel = () => { + if (tabKey == '0') { + return <>; + } else if (tabKey == '1') { + return ( +
+
{ + setDelFollowListShow(!delFollowListShow); + }} + > + 已删联系人 + {delFollowListShow ? : } +
+
+ {custFollowsList.map((item) => { + return item.state == 1 ? null : custFollowsListItem(item); + })} +
+
+ ); + } else { + return ( +
+
{ + setDelGroupListShow(!delGroupListShow); + }} + > + 已解散的群 + {delGroupListShow ? : } +
+
+ {groupList.map((item) => { + return item.state == 1 ? null : groupListItem(item); + })} +
+
+ ); + } + }; + + // 群 Drawer 群员 + const groupMembersListItem = (item: IGroupMembers) => { + return ( +
+
+ {item.avatar ? ( + + ) : item.name ? ( + item.name[0] + ) : ( + '' + )} + {item.user_id == selectGroupRef.current?.owner ? : null} + {selectGroupRef.current?.adminUserIDs?.includes(item.user_id) ? : null} +
+
+ {item.name} +
+
+ ); + }; + return (
@@ -646,6 +666,7 @@ const ChatLogs: React.FC = () => { }} />
{tabContent()}
+ {tabContentDel()}
@@ -687,53 +708,15 @@ const ChatLogs: React.FC = () => { {tabKeyRef.current == '0' ? ( ) : tabKeyRef.current == '1' ? ( -
-
-
- -
-
-
- {selectCustFollow?.name} - -
-
{selectCustFollow?.description}
-
-
-
备注名称:{selectCustFollow?.remark}
-
- 标签 -
- {formatTags(selectCustFollow?.tags)} -
+ ) : (
群主: {groupMembersObjRef.current[selectGroupRef.current?.owner as string]?.name}
-
- {adminList(selectGroupRef.current?.admin_list, groupMembersObjRef.current)} -
-
- 创建时间:{selectGroupRef.current?.create_time} -
+
{adminList(selectGroupRef.current?.admin_list, groupMembersObjRef.current)}
+
创建时间:{selectGroupRef.current?.create_time}
群公告:{selectGroupRef.current?.notice}
{ 群成员 • {groupMembersList.length}
{groupMembersList.map((item) => { - if (item.group_members_type == '2' || item.state == 0) return null; - return ( -
-
- {item.avatar ? ( - - ) : item.name ? ( - item.name[0] - ) : ( - '' - )} -
-
- {item.name} -
-
- ); + return item.group_members_type == '2' || item.state == 0 ? null : groupMembersListItem(item); })} {groupMembersCount2(groupMembersList, '2', 1) != 0 ? (
{
) : null} {groupMembersList.map((item) => { - if (item.group_members_type == '1' || item.state == 0) return null; - return ( -
-
- {item.avatar ? ( - - ) : item.name ? ( - item.name[0] - ) : ( - '' - )} -
-
- {item.name} -
-
- ); + return item.group_members_type == '1' || item.state == 0 ? null : groupMembersListItem(item); })} {groupMembersCount(groupMembersList, 0) != 0 ? (
{
) : null} {groupMembersList.map((item) => { - if (item.state == 1) return null; - return ( -
-
- {item.avatar ? ( - - ) : item.name ? ( - item.name[0] - ) : ( - '' - )} -
-
- {item.name} -
-
- ); + return item.state == 1 ? null : groupMembersListItem(item); })}
)} @@ -931,48 +773,26 @@ const ChatLogs: React.FC = () => { className={styles.chatLogBox} ref={chatBoxRef} onScroll={(e: any) => { - if ( - e.target?.scrollTop == 0 && - !isAllChatRef.current && - !chatLogLoadingRef.current - ) { + if (e.target?.scrollTop == 0 && !isAllChatRef.current && !chatLogLoadingRef.current) { page(param.curr_page + 1); } }} > - {isAllChatRef.current ? ( -
- 没有更多聊天记录了 -
- ) : null} + {isAllChatRef.current ?
没有更多聊天记录了
: null} {chatLogs.map((item) => { if (item.curr_page) { - return ( -
- ); + return
; } else { return (
{/* {item.show_time ? : null} */} {tabKey == '2' ? ( - + ) : ( )} diff --git a/src/pages/CustomList/components/CustDetailContent.tsx b/src/pages/CustomList/components/CustDetailContent.tsx new file mode 100644 index 0000000..763da64 --- /dev/null +++ b/src/pages/CustomList/components/CustDetailContent.tsx @@ -0,0 +1,61 @@ +import { ICustFollow } from '@/pages/ChatLogs/ChatLogsType'; +import { formatTags } from '@/pages/ChatLogs/ChatUtils'; +import { Gender } from '@/pages/ChatLogs/components/Gender'; +import { AddWay, CustType } from '@/services/config'; +import React from 'react'; +import styles from './index.module.scss'; + +type IProps = { + record: ICustFollow; +}; + +/** + * 客户抽屉内容 + * @param props IProps + * @returns + */ +export const CustDetailContent: React.FC = (props) => { + const { record } = props; + return ( +
+
+
+ +
+
+
+ + {record?.name}[{record?.remark}] + + +
+ @{record ? CustType[record?.type] : ''} +
{record?.description}
+
+
+
添加方式:{record ? AddWay[record?.add_way] : ''}
+
跟进员工:{record?.user_id}
+
添加时间:{record?.create_time}
+
+ 标签 +
+ {formatTags(record?.tags)} +
+ ); +}; diff --git a/src/pages/CustomList/index.module.scss b/src/pages/CustomList/components/index.module.scss similarity index 100% rename from src/pages/CustomList/index.module.scss rename to src/pages/CustomList/components/index.module.scss diff --git a/src/pages/CustomList/index.tsx b/src/pages/CustomList/index.tsx index 86d051f..245d30d 100644 --- a/src/pages/CustomList/index.tsx +++ b/src/pages/CustomList/index.tsx @@ -2,56 +2,16 @@ import { SearchBarPlugin, SearchBottonsCardPlugin } from '@/components/SearchBar import { post } from '@/services/ajax'; import { AddWay, CustType } from '@/services/config'; import { PageContainer } from '@ant-design/pro-components'; -import { - Button, - Col, - DatePicker, - Drawer, - Form, - Image, - Input, - Pagination, - Popover, - Row, - Select, - Table, - Tag, -} 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 { formatTags } from '../ChatLogs/ChatUtils'; + +import { ICustFollow } from '../ChatLogs/ChatLogsType'; import { Gender } from '../ChatLogs/components/Gender'; -import styles from './index.module.scss'; - -interface ICustItem { - add_way: number; - avatar: string; - create_time: string; - cust_id: string; - description: string; - gender: number; - name: string; - 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; - type?: number | string; - name?: string; - add_way?: string; - create_timeL?: string; - create_timeU?: string; -}; +import { CustDetailContent } from './components/CustDetailContent'; const CustomList: React.FC = () => { - const [param] = useState({ + const [param] = useState({ curr_page: 1, page_count: 20, type: '', @@ -61,15 +21,15 @@ const CustomList: React.FC = () => { create_timeU: '', }); - const [custsList, setCustsList] = useState([]); + const [custsList, setCustsList] = useState([]); const [count, setCount] = useState(0); const [loading, setLoading] = useState(false); const [open, setOpen] = useState(false); - const [record, setRecord] = useState(); + const [record, setRecord] = useState(); const getCustsList = () => { setLoading(true); - post({ url: '/CustFollows/CustsList', data: stringify(param) }).then((res) => { + post({ url: '/CustFollows/List', data: stringify(param) }).then((res) => { setLoading(false); if (res.err_code == 0) { if (Array.isArray(res.data)) { @@ -192,7 +152,7 @@ const CustomList: React.FC = () => { title="客户" width={200} dataIndex={'name'} - render={(value, record: ICustItem) => { + render={(value, record: ICustFollow) => { return (
{ @@ -221,9 +181,7 @@ const CustomList: React.FC = () => {
- - @{CustType[record.type]} - + @{CustType[record.type]}
@@ -267,19 +225,11 @@ const CustomList: React.FC = () => { ); }} > - + {arr[0]?.tag_name} {arr[1] ? ( - + {arr[1]?.tag_name} ) : null} @@ -289,19 +239,11 @@ const CustomList: React.FC = () => { ) : ( <> - + {arr[0]?.tag_name} {arr[1] ? ( - + {arr[1]?.tag_name} ) : null} @@ -328,53 +270,8 @@ const CustomList: React.FC = () => { {/* */} - setOpen(false)} - width={800} - > -
-
-
- -
-
-
- {record?.name} - -
- - @{record ? CustType[record?.type] : ''} - -
{record?.description}
-
-
-
备注名称:{record?.remark}
-
添加方式:{record ? AddWay[record?.add_way] : ''}
-
跟进员工:{record?.user_id}
-
添加时间:{record?.create_time}
-
- 标签 -
- {formatTags(record?.tags)} -
+ setOpen(false)} width={800}> + = (props) => { )}
-
+
{record?.name}
diff --git a/src/pages/User/Login/index.tsx b/src/pages/User/Login/index.tsx index 190988a..5d123e4 100644 --- a/src/pages/User/Login/index.tsx +++ b/src/pages/User/Login/index.tsx @@ -34,6 +34,7 @@ const Login: React.FC = () => { const [userLoginState, setUserLoginState] = useState({}); const [type, setType] = useState('account'); const { initialState, setInitialState } = useModel('@@initialState'); + const [loading, setLoading] = useState(false); const containerClassName = useEmotionCss(() => { return { @@ -52,12 +53,14 @@ const Login: React.FC = () => { window.NotificationCF = notification; const handleSubmit = async (values: API.LoginParams) => { + setLoading(true); const data = { user: values.username, password: values.password, }; post({ url: '/User/Login', data: qsStringify(data) }).then((res: IAjaxReturn) => { + setLoading(false); if (res && res.err_code == 0) { notification.success({ message: '登录成功', @@ -91,6 +94,7 @@ const Login: React.FC = () => { }} > {
} count={data.overView.custs_total} /> } count={data.overView.groups_total} /> } count={data.overView.groups_members_total} /> @@ -125,31 +125,31 @@ const Workbench: React.FC = () => {
{/* */} {/* */} {/* {
diff --git a/src/services/ajax.ts b/src/services/ajax.ts index 811d33b..8388b75 100644 --- a/src/services/ajax.ts +++ b/src/services/ajax.ts @@ -18,13 +18,17 @@ export const post = async (param: IPost) => { const { url, data, showError = true } = param; return await request('/api' + url, { data: data, - }).then((res: IAjaxReturn) => { - if (res.err_code != 0 && showError) { - notificationError({ - message: `${res.err_msg}`, - description: `${res.err_code}:${res.err_msg}`, - }); - } - return res; - }); + }) + .then((res: IAjaxReturn) => { + if (res.err_code != 0 && showError) { + notificationError({ + message: `${res.err_msg}`, + description: `${res.err_code}:${res.err_msg}`, + }); + } + return res; + }) + .catch((res) => { + return res; + }); };