开发: 部分页面兼容小屏幕

This commit is contained in:
zhengw
2023-04-28 17:25:47 +08:00
parent 24ab30f1a0
commit 297ab0778d
10 changed files with 533 additions and 313 deletions

View File

@@ -6,6 +6,7 @@ import React, { useState } from 'react';
interface IProps { interface IProps {
body: React.ReactNode; body: React.ReactNode;
footer: React.ReactNode; footer: React.ReactNode;
phoneBtns?: React.ReactNode;
} }
export const SearchBarPlugin: React.FC<IProps> = (props) => { export const SearchBarPlugin: React.FC<IProps> = (props) => {
@@ -43,7 +44,7 @@ export const SearchBarPlugin: React.FC<IProps> = (props) => {
<> <>
{isPhone ? ( {isPhone ? (
<> <>
<Drawer title="筛选条件" open={open} onClose={() => setOpen(false)} width={'80%'}> <Drawer title="筛选条件" open={open} onClose={() => setOpen(false)} width={'85%'}>
<div>{props.body}</div> <div>{props.body}</div>
<div <div
style={{ paddingBottom: 16 }} style={{ paddingBottom: 16 }}
@@ -59,10 +60,11 @@ export const SearchBarPlugin: React.FC<IProps> = (props) => {
background: '#fff', background: '#fff',
display: 'flex', display: 'flex',
justifyContent: 'flex-end', justifyContent: 'flex-end',
padding: '8px 0', padding: '8px 12px',
borderRadius: 6, borderRadius: 6,
}} }}
> >
{props.phoneBtns}
<Button <Button
type="default" type="default"
onClick={() => { onClick={() => {

View File

@@ -65,6 +65,7 @@ export interface ICustFollow {
} }
export interface IGroup { export interface IGroup {
members_tot?: number;
admin_list: string; admin_list: string;
avatar?: string; avatar?: string;
adminUserIDs: string[]; adminUserIDs: string[];

View File

@@ -5,6 +5,7 @@
* @returns * @returns
*/ */
import { Image } from 'antd';
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { IGroup, IGroupMembers } from './ChatLogsType'; import { IGroup, IGroupMembers } from './ChatLogsType';
import { AdminSvg, OwnerSvg } from './components/Svgs'; import { AdminSvg, OwnerSvg } from './components/Svgs';
@@ -52,6 +53,7 @@ export const groupMembersListItem = (item: IGroupMembers, selectGroup: IGroup) =
verticalAlign: 'top', verticalAlign: 'top',
marginTop: 12, marginTop: 12,
}} }}
title={item.name}
> >
<div <div
style={{ style={{
@@ -63,12 +65,12 @@ export const groupMembersListItem = (item: IGroupMembers, selectGroup: IGroup) =
width: 56, width: 56,
height: 56, height: 56,
lineHeight: 1, lineHeight: 1,
background: '#69b1ff', background: '#cfd1d4',
borderRadius: 4, borderRadius: 4,
}} }}
> >
{item.avatar ? ( {item.avatar ? (
<img <Image
style={{ style={{
maxWidth: '100%', maxWidth: '100%',
maxHeight: '100%', maxHeight: '100%',
@@ -96,7 +98,6 @@ export const groupMembersListItem = (item: IGroupMembers, selectGroup: IGroup) =
width: 72, width: 72,
textAlign: 'center', textAlign: 'center',
}} }}
title={item.name}
> >
{item.name} {item.name}
</div> </div>
@@ -250,7 +251,7 @@ export const GroupIcon: React.FC<IGroupIcon> = (props) => {
alignItems: 'center', alignItems: 'center',
}} }}
> >
<div style={{ transform: 'scale(0.65)', lineHeight: 1 }}>{el.name[0]}</div> <div style={{ transform: 'scale(0.65)' }}>{el.name ? el.name[0] : ''}</div>
</div> </div>
)} )}
</div> </div>

View File

@@ -258,15 +258,9 @@ const ChatLogs: React.FC = () => {
}; };
// 监听DOM变动 // 监听DOM变动
const callback = function (mutationsList: any) { const callback = function () {
// Use traditional 'for loops' for IE 11 // Use traditional 'for loops' for IE 11
for (let mutation of mutationsList) { document.querySelector('.curr_page' + param.curr_page)?.scrollIntoView(true);
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); const observer = new MutationObserver(callback);

View File

@@ -3,7 +3,7 @@ import { formatTags } from '@/pages/ChatLogs/ChatUtils';
import { Gender } from '@/pages/ChatLogs/components/Gender'; import { Gender } from '@/pages/ChatLogs/components/Gender';
import { post } from '@/services/ajax'; import { post } from '@/services/ajax';
import { AddWay, CustType } from '@/services/config'; import { AddWay, CustType } from '@/services/config';
import { Spin, Steps } from 'antd'; import { Image, Spin, Steps } from 'antd';
import { stringify } from 'qs'; import { stringify } from 'qs';
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import styles from './index.module.scss'; import styles from './index.module.scss';
@@ -63,7 +63,7 @@ export const CustDetailContent: React.FC<IProps> = (props) => {
}} }}
> >
<div className={styles.modalAvatar}> <div className={styles.modalAvatar}>
<img src={record?.avatar} alt="" /> <Image src={record?.avatar} alt="" />
</div> </div>
<div style={{ display: 'flex', flexDirection: 'column' }}> <div style={{ display: 'flex', flexDirection: 'column' }}>
<div style={{ fontSize: 16, display: 'flex', alignItems: 'center' }}> <div style={{ fontSize: 16, display: 'flex', alignItems: 'center' }}>
@@ -77,7 +77,7 @@ export const CustDetailContent: React.FC<IProps> = (props) => {
</div> </div>
</div> </div>
<div>{record ? AddWay[record?.add_way] : ''}</div> <div>{record ? AddWay[record?.add_way] : ''}</div>
<div>{record?.user_id}</div> <div>{record?.staff_name}</div>
<div>{record?.create_time}</div> <div>{record?.create_time}</div>
<div <div
style={{ style={{

View File

@@ -4,6 +4,7 @@ import { AddWay, CustType } from '@/services/config';
import { PageContainer } from '@ant-design/pro-components'; import { PageContainer } from '@ant-design/pro-components';
import { import {
Button, Button,
Card,
Col, Col,
DatePicker, DatePicker,
Drawer, Drawer,
@@ -14,6 +15,7 @@ import {
Popover, Popover,
Row, Row,
Select, Select,
Spin,
Table, Table,
Tag, Tag,
} from 'antd'; } from 'antd';
@@ -188,182 +190,226 @@ const CustomList: React.FC = () => {
</Row> </Row>
} }
/> />
{isPhone ? (
<Table <Spin spinning={loading}>
tableLayout="fixed" {custsList.map((item) => {
size="middle"
dataSource={custsList}
style={{ padding: 16, borderRadius: 6, background: '#fff', marginTop: 16 }}
pagination={false}
bordered={true}
rowKey={(record) => {
return `${record.cust_id}_${record.user_id}`;
}}
loading={loading}
onRow={(record: ICustFollow) => {
if (
record?.add_staff_tot &&
!isNaN(record?.add_staff_tot) &&
Number(record?.add_staff_tot) > 1
) {
return {
style: {
background: '#fcffe6',
},
};
}
return {};
}}
>
<Table.Column
title="客户"
width={200}
dataIndex={'name'}
render={(value, record: ICustFollow) => {
return ( return (
<div <Card
key={`${item.cust_id}_${item.user_id}`}
style={{ marginTop: 16 }}
onClick={() => { onClick={() => {
setRecord(record); setRecord(item);
setOpen(true); setOpen(true);
}} }}
style={{ cursor: 'pointer', display: 'flex' }}
> >
<div <div style={{ display: 'flex' }}>
style={{ <div
width: 56, style={{
height: 56, width: 56,
flexShrink: 0, height: 56,
borderRadius: 4, flexShrink: 0,
overflow: 'hidden', borderRadius: 4,
}} overflow: 'hidden',
onClick={(e) => { }}
e.stopPropagation(); onClick={(e) => {
}} e.stopPropagation();
> }}
<Image width={56} height={56} src={record.avatar} /> >
</div> <Image width={56} height={56} src={item.avatar} />
<div style={{ marginLeft: 8 }}>
<div style={{ color: '#1890ff', wordBreak: 'break-all' }}>
{value}[{record.remark}]
</div> </div>
<div style={{ display: 'flex', alignItems: 'center' }}> <div style={{ marginLeft: 8 }}>
<Gender gender={record.gender} /> <div style={{ color: '#1890ff', wordBreak: 'break-all' }}>
<span style={{ marginLeft: 4, color: '#389e0d' }}> {item.name}[{item.remark}]
@{CustType[record.type]} </div>
</span> <div style={{ display: 'flex', alignItems: 'center' }}>
<Gender gender={item.gender} />
<span style={{ marginLeft: 4, color: '#389e0d' }}>
@{CustType[item.type]}
</span>
</div>
</div> </div>
</div> </div>
</div> </Card>
); );
})}
</Spin>
) : (
<Table
tableLayout="fixed"
size="middle"
dataSource={custsList}
style={{ padding: 16, borderRadius: 6, background: '#fff', marginTop: 16 }}
pagination={false}
bordered={true}
rowKey={(record) => {
return `${record.cust_id}_${record.user_id}`;
}} }}
/> loading={loading}
<Table.Column onRow={(record: ICustFollow) => {
title="客户标签" if (
width={160} record?.add_staff_tot &&
onCell={() => { !isNaN(record?.add_staff_tot) &&
return { Number(record?.add_staff_tot) > 1
style: { ) {
paddingBottom: 8, return {
}, style: {
}; background: '#fcffe6',
}} },
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>
) : (
<div>
<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}
</div>
)}
</>
);
}
} catch (e) {
/* empty */
} }
return <div style={{ marginBottom: 4 }}></div>; return {};
}} }}
dataIndex={'tags'} >
/> <Table.Column
<Table.Column title="客户"
title="跟进员工" width={200}
width={120} dataIndex={'name'}
render={(v, record: ICustFollow) => { render={(value, record: ICustFollow) => {
return <>{record?.staff_name}</>; return (
}} <div
dataIndex={'user_id'} onClick={() => {
/> setRecord(record);
{/* <Table.Column title="商机阶段" width={160} dataIndex={'position'} /> */} setOpen(true);
<Table.Column }}
title="添加方式" style={{ cursor: 'pointer', display: 'flex' }}
width={120} >
dataIndex={'add_way'} <div
render={(value) => { style={{
return <>{AddWay[value]}</>; width: 56,
}} height: 56,
/> flexShrink: 0,
<Table.Column title="添加时间" width={120} dataIndex={'create_time'} /> borderRadius: 4,
{/* <Table.Column title="操作" width={160} dataIndex={'position'} /> */} overflow: 'hidden',
</Table> }}
onClick={(e) => {
e.stopPropagation();
}}
>
<Image width={56} height={56} src={record.avatar} />
</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} />
<span style={{ marginLeft: 4, color: '#389e0d' }}>
@{CustType[record.type]}
</span>
</div>
</div>
</div>
);
}}
/>
<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>
) : (
<div>
<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}
</div>
)}
</>
);
}
} catch (e) {
/* empty */
}
return <div style={{ marginBottom: 4 }}></div>;
}}
dataIndex={'tags'}
/>
<Table.Column
title="跟进员工"
width={120}
render={(v, record: ICustFollow) => {
return <>{record?.staff_name}</>;
}}
dataIndex={'user_id'}
/>
{/* <Table.Column title="商机阶段" width={160} dataIndex={'position'} /> */}
<Table.Column
title="添加方式"
width={120}
dataIndex={'add_way'}
render={(value) => {
return <>{AddWay[value]}</>;
}}
/>
<Table.Column title="添加时间" width={120} dataIndex={'create_time'} />
{/* <Table.Column title="操作" width={160} dataIndex={'position'} /> */}
</Table>
)}
<Drawer <Drawer
title={`${record?.name} 客户详情`} title={`${record?.name} 客户详情`}
open={open} open={open}
@@ -373,6 +419,7 @@ const CustomList: React.FC = () => {
<CustDetailContent record={record as ICustFollow} /> <CustDetailContent record={record as ICustFollow} />
</Drawer> </Drawer>
<Pagination <Pagination
size={isPhone ? 'small' : 'default'}
style={{ style={{
background: '#fff', background: '#fff',
borderRadius: 6, borderRadius: 6,
@@ -386,7 +433,7 @@ const CustomList: React.FC = () => {
pageSize={param.page_count} pageSize={param.page_count}
total={count} total={count}
pageSizeOptions={[10, 20, 50, 100]} pageSizeOptions={[10, 20, 50, 100]}
onShowSizeChange={(current, size) => { onShowSizeChange={(_current, size) => {
param.page_count = size; param.page_count = size;
page(1); page(1);
}} }}

View File

@@ -1,9 +1,11 @@
import { SearchBarPlugin } from '@/components/SearchBarPlugin'; import { SearchBarPlugin } from '@/components/SearchBarPlugin';
import { post } from '@/services/ajax'; import { post } from '@/services/ajax';
import { getDevice } from '@/services/utils';
import { PageContainer } from '@ant-design/pro-components'; import { PageContainer } from '@ant-design/pro-components';
import { import {
App, App,
Button, Button,
Card,
Col, Col,
Drawer, Drawer,
Form, Form,
@@ -58,7 +60,9 @@ const DepartmentsList: React.FC = () => {
const [loadingL, setLoadingL] = useState(false); const [loadingL, setLoadingL] = useState(false);
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
const [phoneDepOpen, setPhoneDepOpen] = useState(false);
const [record, setRecord] = useState<IStaffsItem>(); const [record, setRecord] = useState<IStaffsItem>();
const isPhone = getDevice() == 'phone';
const getStaffsList = () => { const getStaffsList = () => {
setLoading(true); setLoading(true);
@@ -145,26 +149,93 @@ const DepartmentsList: React.FC = () => {
return ( return (
<PageContainer> <PageContainer>
<div style={{ display: 'flex' }}> <Drawer
<div title="部门"
style={{ open={phoneDepOpen}
width: 240, onClose={() => setPhoneDepOpen(false)}
flexShrink: 0, width={'85%'}
minHeight: 'calc(100vh - 55px - 60px - 96px)', placement="left"
maxHeight: 'calc(100vh - 55px - 60px)', >
overflow: 'auto', <Tree
marginRight: 12, className={'department-tree'}
background: '#fff', blockNode
position: 'sticky', key={departmentsList.length}
top: 64, selectedKeys={[departmentID]}
padding: '12px 0', defaultExpandAll
treeData={departmentsList as any}
fieldNames={{ title: 'name', key: 'id' }}
onSelect={(selectedKeys) => {
setPhoneDepOpen(false);
if (selectedKeys.length) {
setDepartmentsID(Number(selectedKeys[0]));
param.dep_id = Number(selectedKeys[0]);
page(1);
}
}} }}
> titleRender={(nodeData: any) => {
<Spin spinning={loadingL} style={{ display: 'block' }}> // console.log(nodeData);
{departmentsList.length ? ( return (
<div className={styles.departmentItem}>
<div className={styles.name} title={nodeData.name}>
{nodeData.name}
</div>
{/* <div className={styles.btnsBox}>
<FormOutlined
title="修改"
onClick={(e) => {
e.stopPropagation();
setOpen(true);
}}
className={styles.edit}
/>
<Popconfirm
title="确认删除?"
open={popOpen == nodeData.id}
onCancel={(e) => {
setPopOpen(-1);
e?.stopPropagation();
}}
onConfirm={(e) => {
e?.stopPropagation();
console.log(nodeData.id);
}}
>
<DeleteOutlined
title="删除"
onClick={(e) => {
e.stopPropagation();
setPopOpen(nodeData.id);
}}
className={styles.del}
/>
</Popconfirm>
</div> */}
</div>
);
}}
/>
</Drawer>
<div style={{ display: 'flex' }}>
{isPhone ? null : (
<div
style={{
width: 240,
flexShrink: 0,
minHeight: 'calc(100vh - 55px - 60px - 96px)',
maxHeight: 'calc(100vh - 55px - 60px)',
overflow: 'auto',
marginRight: 12,
background: '#fff',
position: 'sticky',
top: 64,
padding: '12px 0',
}}
>
<Spin spinning={loadingL} style={{ display: 'block' }}>
<Tree <Tree
className={'department-tree'} className={'department-tree'}
blockNode blockNode
key={departmentsList.length}
selectedKeys={[departmentID]} selectedKeys={[departmentID]}
defaultExpandAll defaultExpandAll
treeData={departmentsList as any} treeData={departmentsList as any}
@@ -218,9 +289,9 @@ const DepartmentsList: React.FC = () => {
); );
}} }}
/> />
) : null} </Spin>
</Spin> </div>
</div> )}
<Modal <Modal
title="系统提示" title="系统提示"
open={!!syncOpen} open={!!syncOpen}
@@ -320,70 +391,127 @@ const DepartmentsList: React.FC = () => {
</Button> </Button>
</Row> </Row>
} }
phoneBtns={
isPhone ? (
<Button
type="primary"
style={{ marginRight: 12 }}
onClick={() => {
setPhoneDepOpen(true);
}}
>
</Button>
) : null
}
/> />
{isPhone ? (
<Table <Spin spinning={loading}>
tableLayout="fixed" {staffsData.data?.map((item) => {
size="middle"
dataSource={staffsData.data}
style={{ padding: 16, borderRadius: 6, background: '#fff', marginTop: 16 }}
pagination={false}
bordered={true}
rowKey={'user_id'}
loading={loading}
>
<Table.Column
title="姓名"
dataIndex={'name'}
render={(value, record: IStaffsItem) => {
return ( return (
<div <Card
onClick={() => { onClick={() => {
setRecord(record); setRecord(item);
setOpen(true); setOpen(true);
}} }}
style={{ color: '#1890ff', cursor: 'pointer' }} key={item.user_id}
title={<span style={{ color: '#1890ff' }}>{item.name}</span>}
style={{ marginTop: 16 }}
extra={
item.isleader == 1 ? (
<span
style={{
color: '#999',
fontSize: 12,
border: '1px solid #ddd',
borderRadius: 4,
padding: '2px 4px',
}}
>
</span>
) : null
}
> >
<span <div>{item.position || '未设置'}</div>
style={{ <div>{item?.dep_name?.join('') || '未设置'}</div>
display: 'inline-block', <div>{item.mobile || '未设置'}</div>
marginRight: record.isleader == 1 ? 4 : 0, <div>{item.biz_mail || '未设置'}</div>
</Card>
);
})}
</Spin>
) : (
<Table
tableLayout="fixed"
size="middle"
dataSource={staffsData.data}
style={{ padding: 16, borderRadius: 6, background: '#fff', marginTop: 16 }}
pagination={false}
bordered={true}
rowKey={'user_id'}
loading={loading}
>
<Table.Column
title="姓名"
dataIndex={'name'}
render={(value, record: IStaffsItem) => {
return (
<div
onClick={() => {
setRecord(record);
setOpen(true);
}} }}
style={{ color: '#1890ff', cursor: 'pointer' }}
> >
{value}
</span>
{record?.isleader == 1 ? (
<span <span
style={{ style={{
color: '#999', display: 'inline-block',
fontSize: 12, marginRight: record.isleader == 1 ? 4 : 0,
border: '1px solid #ddd',
borderRadius: 4,
padding: '2px 4px',
}} }}
> >
{value}
</span> </span>
) : null} {record?.isleader == 1 ? (
</div> <span
); style={{
}} color: '#999',
/> fontSize: 12,
<Table.Column title="职务" width={160} dataIndex={'position'} /> border: '1px solid #ddd',
<Table.Column borderRadius: 4,
title="部门" padding: '2px 4px',
dataIndex={'dep_name'} }}
render={(val) => { >
return <>{val.join('')}</>;
}} </span>
/> ) : null}
<Table.Column title="手机号" width={160} dataIndex={'mobile'} /> </div>
<Table.Column title="企业邮箱" dataIndex={'biz_mail'} /> );
</Table> }}
<Drawer title="成员详情" open={open} onClose={() => setOpen(false)} width={800}> />
<Table.Column title="职务" width={160} dataIndex={'position'} />
<Table.Column
title="部门"
dataIndex={'dep_name'}
render={(val) => {
return <>{val.join('')}</>;
}}
/>
<Table.Column title="手机号" width={160} dataIndex={'mobile'} />
<Table.Column title="企业邮箱" dataIndex={'biz_mail'} />
</Table>
)}
<Drawer
title="成员详情"
open={open}
onClose={() => setOpen(false)}
width={isPhone ? '90%' : 800}
destroyOnClose
>
<DepartmentMembersDetail record={record as IStaffsItem} /> <DepartmentMembersDetail record={record as IStaffsItem} />
</Drawer> </Drawer>
<Pagination <Pagination
size={isPhone ? 'small' : 'default'}
style={{ style={{
background: '#fff', background: '#fff',
borderRadius: 6, borderRadius: 6,

View File

@@ -9,6 +9,7 @@ import {
groupMembersCount2, groupMembersCount2,
groupMembersListItem, groupMembersListItem,
} from '@/pages/ChatLogs/ChatUtils'; } from '@/pages/ChatLogs/ChatUtils';
import { getDevice } from '@/services/utils';
import { Spin } from 'antd'; import { Spin } from 'antd';
import { stringify } from 'qs'; import { stringify } from 'qs';
import styles from './index.mudule.scss'; import styles from './index.mudule.scss';
@@ -22,7 +23,7 @@ export const GroupDetailContent: React.FC<Iprops> = (props) => {
const [groupMembersList, setGroupMembersList] = useState<IGroupMembers[]>([]); const [groupMembersList, setGroupMembersList] = useState<IGroupMembers[]>([]);
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const groupMembersObjRef = useRef<any>({}); const groupMembersObjRef = useRef<any>({});
const isPhone = getDevice() === 'phone';
const getList = () => { const getList = () => {
setLoading(true); setLoading(true);
post({ post({
@@ -60,10 +61,10 @@ export const GroupDetailContent: React.FC<Iprops> = (props) => {
}, [props.record]); }, [props.record]);
return ( return (
<Spin spinning={loading} style={{ minHeight: 400, display: 'block' }}> <Spin spinning={loading} style={{ minHeight: isPhone ? 'auto' : 400, display: 'block' }}>
{groupMembersList.length ? ( {groupMembersList.length ? (
<div> <div>
<div className={styles.groupMsgBox}> <div className={styles.groupMsgBox} style={{ flexDirection: isPhone ? 'column' : 'row' }}>
<div className={styles.groupMsg}> <div className={styles.groupMsg}>
<div style={{ marginBottom: 8, textIndent: '2em' }}> <div style={{ marginBottom: 8, textIndent: '2em' }}>
@@ -74,7 +75,10 @@ export const GroupDetailContent: React.FC<Iprops> = (props) => {
</div> </div>
<div style={{ marginBottom: 8 }}>{record?.create_time}</div> <div style={{ marginBottom: 8 }}>{record?.create_time}</div>
</div> </div>
<div className={styles.notice}> <div
className={styles.notice}
style={{ width: isPhone ? '100%' : '', marginTop: isPhone ? 16 : 0 }}
>
<div style={{ textIndent: '1em' }}> <div style={{ textIndent: '1em' }}>
<div <div
style={{ style={{

View File

@@ -1,7 +1,6 @@
.groupMsgBox { .groupMsgBox {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
min-height: 100px;
} }
.groupMsg { .groupMsg {

View File

@@ -2,10 +2,24 @@ import { SearchBarPlugin } from '@/components/SearchBarPlugin';
import { post } from '@/services/ajax'; import { post } from '@/services/ajax';
import { groupStatus } from '@/services/config'; import { groupStatus } from '@/services/config';
import { PageContainer } from '@ant-design/pro-components'; import { PageContainer } from '@ant-design/pro-components';
import { Button, Col, DatePicker, Drawer, Form, Input, Pagination, Row, Select, Table } from 'antd'; import {
Button,
Card,
Col,
DatePicker,
Drawer,
Form,
Input,
Pagination,
Row,
Select,
Spin,
Table,
} from 'antd';
import { stringify } from 'qs'; import { stringify } from 'qs';
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { getDevice } from '@/services/utils';
import { IGroup } from '../ChatLogs/ChatLogsType'; import { IGroup } from '../ChatLogs/ChatLogsType';
import { GroupDetailContent } from './components/GroupDetailContent'; import { GroupDetailContent } from './components/GroupDetailContent';
@@ -20,7 +34,7 @@ const GroupList: React.FC = () => {
create_timeL: '', create_timeL: '',
create_timeU: '', create_timeU: '',
}); });
const isPhone = getDevice() === 'phone';
const [groupsList, setGroupsList] = useState<IGroup[]>([]); const [groupsList, setGroupsList] = useState<IGroup[]>([]);
const [count, setCount] = useState(0); const [count, setCount] = useState(0);
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
@@ -145,33 +159,61 @@ const GroupList: React.FC = () => {
</Row> </Row>
} }
/> />
{isPhone ? (
<Table <Spin spinning={loading}>
tableLayout="fixed" {groupsList.map((item) => {
size="middle"
dataSource={groupsList}
style={{ padding: 16, borderRadius: 6, background: '#fff', marginTop: 16 }}
pagination={false}
bordered={true}
rowKey={(record) => {
return `${record.group_id}_${record.name}`;
}}
loading={loading}
>
<Table.Column
title="群名"
width={160}
dataIndex={'name'}
render={(value, record: IGroup) => {
return ( return (
<div <Card
key={`${item.group_id}_${item.name}`}
onClick={() => { onClick={() => {
setRecord(record); setRecord(item);
setOpen(true); setOpen(true);
}} }}
style={{ cursor: 'pointer', display: 'flex' }} style={{ marginTop: 16 }}
title={
<div style={{ color: '#1890ff', wordBreak: 'break-all' }}>
{item.name || '未知群名'}
</div>
}
extra={
<span style={{ color: '#999' }}>{item.state == 1 ? '正常' : '已解散'}</span>
}
> >
{/* <div <div>{item.staff_name}</div>
<div>{item?.members_tot}</div>
<div>{groupStatus[item.status]}</div>
<div>{item.create_time}</div>
</Card>
);
})}
</Spin>
) : (
<Table
tableLayout="fixed"
size="middle"
dataSource={groupsList}
style={{ padding: 16, borderRadius: 6, background: '#fff', marginTop: 16 }}
pagination={false}
bordered={true}
rowKey={(record) => {
return `${record.group_id}_${record.name}`;
}}
loading={loading}
>
<Table.Column
title="群名"
width={160}
dataIndex={'name'}
render={(value, record: IGroup) => {
return (
<div
onClick={() => {
setRecord(record);
setOpen(true);
}}
style={{ cursor: 'pointer', display: 'flex' }}
>
{/* <div
style={{ style={{
width: 56, width: 56,
height: 56, height: 56,
@@ -185,52 +227,54 @@ const GroupList: React.FC = () => {
> >
<Image width={56} height={56} src={record.avatar}></Image> <Image width={56} height={56} src={record.avatar}></Image>
</div> */} </div> */}
<div style={{ marginLeft: 8 }}>
<div style={{ color: '#1890ff', wordBreak: 'break-all' }}> <div style={{ color: '#1890ff', wordBreak: 'break-all' }}>
{value || '未知群名'} {value || '未知群名'}
</div> </div>
</div> </div>
</div> );
); }}
}} />
/> <Table.Column
<Table.Column title="群主"
title="群主" width={120}
width={120} render={(v, r: IGroup) => {
render={(v, r: IGroup) => { return <>{r?.staff_name}</>;
return <>{r?.staff_name}</>; }}
}} dataIndex={'owner'}
dataIndex={'owner'} />
/> <Table.Column
<Table.Column title="状态"
title="状态" width={120}
width={120} render={(v) => {
render={(v) => { return <>{groupStatus[v]}</>;
return <>{groupStatus[v]}</>; }}
}} dataIndex={'status'}
dataIndex={'status'} />
/> <Table.Column title="群人数" width={120} dataIndex={'members_tot'} />
<Table.Column title="群人数" width={120} dataIndex={'members_tot'} /> <Table.Column
<Table.Column title="是否解散"
title="是否解散" width={140}
width={140} render={(v) => {
render={(v) => { return <>{v == 1 ? '正常' : '已解散'}</>;
return <>{v == 1 ? '正常' : '已解散'}</>; }}
}} dataIndex={'state'}
dataIndex={'state'} />
/> <Table.Column title="创建时间" width={140} dataIndex={'create_time'} />
<Table.Column title="创建时间" width={140} dataIndex={'create_time'} /> {/* <Table.Column title="操作" width={160} dataIndex={'position'} /> */}
{/* <Table.Column title="操作" width={160} dataIndex={'position'} /> */} </Table>
</Table> )}
<Drawer <Drawer
title={`${record?.name} 群详情`} title={`${record?.name || '未知群名'} 群详情`}
open={open} open={open}
onClose={() => setOpen(false)} onClose={() => setOpen(false)}
width={800} width={isPhone ? '90%' : 800}
> >
<GroupDetailContent record={record as IGroup} /> <GroupDetailContent record={record as IGroup} />
</Drawer> </Drawer>
<Pagination <Pagination
size={isPhone ? 'small' : 'default'}
style={{ style={{
background: '#fff', background: '#fff',
borderRadius: 6, borderRadius: 6,