import { Comment, Dropdown, Input, List, Menu } from 'antd'; import produce from 'immer'; import _ from 'lodash'; import React, { useCallback, useEffect, useState } from 'react'; import { useChannel } from '../hooks/useWebSocket'; import { deleteRoom, getRoomList, postCreateRoom } from '../services/chat'; import styles from '../style.module.css'; import dayjs from '../utils/dayjs'; import CreateModal from './ChatModal'; import IconFont from './IconFonts'; type PropType = { username: string; room_id: string; chat?: any; onChatSet?: (chat: any) => void; to: (room_id?: string) => void; user_id: string; members: any[]; }; const RoomList: React.FC = ({ username, room_id, chat, onChatSet, to, user_id, members, }) => { const [rooms, setRooms] = useState([]); const [searchText, setSearchText] = useState(''); const [visible, setVisible] = useState(false); const [allowUserIds, setAllowUserIds] = useState([]); const [indeterminate, setIndeterminate] = React.useState(false); const [checkAll, setCheckAll] = React.useState(false); const onCheckAllChange = (e) => { setAllowUserIds(e.target.checked ? members.filter((s) => s.user_id !== user_id).map((v) => v.user_id) : []); setIndeterminate(false); setCheckAll(e.target.checked); }; useEffect(() => { getRoomList(username).then((res) => { setRooms(res); }); }, [username]); useChannel(`chat-room-info-${username}`, username, (obj: Chat.ChannelType) => { if (obj) { const { data } = obj; const newRooms = _.clone(rooms as Chat.RoomInfo[]); switch (data.op) { case 'create': { setRooms(_.concat(newRooms, [data.room])); if (chat?.room?.id === data.id && onChatSet) { onChatSet( produce((draft: any) => { draft.room = { ...chat.room, ...data.room }; }) ); } break; } case 'delete': { setRooms(_.filter(newRooms, (room) => room.id !== data.id)); if (chat?.room?.id === data.id && onChatSet) { onChatSet( produce((draft: any) => { draft.room = undefined; }) ); to(); } break; } case 'update': { const roomIndex = _.findIndex(rooms, ['id', data.id]); newRooms[roomIndex] = { ...rooms[roomIndex], ...data.room }; setRooms(newRooms); if (chat?.room?.id === data.id && onChatSet) { onChatSet( produce((draft: any) => { draft.room = { ...chat.room, ...data.room }; }) ); } break; } default: break; } } }); const checked = (v) => { return allowUserIds.includes(v.user_id) || user_id === v.user_id; }; const disabled = (v) => { return user_id === v.user_id; }; const roomTitle = useCallback( (item: Chat.RoomInfo) => { return ( item.name || _.filter(members, (m) => _.includes(item.allow_user_ids, m.user_id)) .map((m) => m.user_name) .join('、') ); }, [members] ); const lastMessage = useCallback((messages?: Chat.Message[]) => { return messages ? _.reduce( messages, (result, v) => { if (v.type === 'attachment') { return result + (v?.sub_type || '') === 'image' ? '[图片]' : '[文件]'; } return result + v.text; }, '' ) : '暂无消息'; }, []); return ( <> dataSource={rooms.filter((v) => v.name?.includes(searchText))} itemLayout="horizontal" header={ setSearchText(e.target.value)} allowClear suffix={ { setVisible(true); }} /> } /> } renderItem={(item) => ( , onClick: () => { deleteRoom(username, item.id); to(); }, }, ]} /> } trigger={['contextMenu']} >
  • { to(item.id); }} > {roomTitle(item)}} content={

    {lastMessage(item.last_record?.message)}

    {item.last_record?.message ? dayjs(item.last_record.created_at).fromNow() : ''}
    } avatar={
      {item.allow_user_ids && members .filter((v) => item.allow_user_ids.includes(v.user_id) && v.avatar.includes('https')) .slice(0, 9) .map((m) => (
    • ))}
    } />
  • )} /> user_id != null && postCreateRoom(username, roomName, allowUserIds.concat([user_id])).then(() => setVisible(false)) } disabled={(v) => disabled(v)} checked={(v) => checked(v)} title="创建房间" okText="创建" /> ); }; export default RoomList;