import React, { useState, useEffect, useRef } from 'react'
import { Card, Button, Input, List, Badge, Modal, Form, Select, Tabs, Avatar, Empty, message, Popconfirm, Space, Tag, Tooltip } from 'antd'
import { PlusOutlined, SendOutlined, TeamOutlined, UserOutlined, ArrowLeftOutlined, DeleteOutlined, SettingOutlined, UserDeleteOutlined } from '@ant-design/icons'
import axios from 'axios'
const { TextArea } = Input
// 移动端检测
function useIsMobile() {
const [isMobile, setIsMobile] = useState(window.innerWidth < 768)
useEffect(() => {
const onResize = () => setIsMobile(window.innerWidth < 768)
window.addEventListener('resize', onResize)
return () => window.removeEventListener('resize', onResize)
}, [])
return isMobile
}
function Messages({ user }) {
const isMobile = useIsMobile()
const [conversations, setConversations] = useState([])
const [allUsers, setAllUsers] = useState([])
const [activeConv, setActiveConv] = useState(null)
const [messages, setMessages] = useState([])
const [inputValue, setInputValue] = useState('')
const [sending, setSending] = useState(false)
const [createVisible, setCreateVisible] = useState(false)
const [membersVisible, setMembersVisible] = useState(false)
const [createForm] = Form.useForm()
const [creating, setCreating] = useState(false)
const bottomRef = useRef(null)
const activeConvRef = useRef(null)
const lastMsgIdRef = useRef(0)
// 打开会话时同步到 ref(供轮询闭包使用)
const openConversation = (conv) => {
setActiveConv(conv)
activeConvRef.current = conv
lastMsgIdRef.current = 0
setMessages([])
}
const closeConversation = () => {
setActiveConv(null)
activeConvRef.current = null
setMessages([])
}
const fetchConversations = async () => {
try {
const res = await axios.get('/api/chat/conversations')
if (res.data.success) setConversations(res.data.data)
} catch (err) { /* 静默 */ }
}
const fetchUsers = async () => {
try {
const res = await axios.get('/api/chat/users')
if (res.data.success) setAllUsers(res.data.data)
} catch (err) { /* 静默 */ }
}
// 拉取当前打开会话的消息(首次全量,之后增量)
const fetchMessages = async (conv) => {
if (!conv) return
try {
const after = lastMsgIdRef.current
const res = await axios.get(`/api/chat/conversations/${conv.id}/messages`, { params: after ? { after } : {} })
if (res.data.success) {
const rows = res.data.data
if (rows.length > 0) {
lastMsgIdRef.current = rows[rows.length - 1].id
setMessages(prev => after > 0 ? [...prev, ...rows] : rows)
}
}
} catch (err) { /* 静默 */ }
}
// 会话列表 5 秒轮询;打开的会话 3 秒轮询消息
useEffect(() => {
fetchConversations()
fetchUsers()
const convTimer = setInterval(fetchConversations, 5000)
const msgTimer = setInterval(() => fetchMessages(activeConvRef.current), 3000)
return () => { clearInterval(convTimer); clearInterval(msgTimer) }
}, [])
// 新消息自动滚动到底部
useEffect(() => {
bottomRef.current?.scrollIntoView({ behavior: 'smooth' })
}, [messages.length])
const handleSend = async () => {
const content = inputValue.trim()
if (!content || !activeConv || sending) return
setSending(true)
try {
const res = await axios.post(`/api/chat/conversations/${activeConv.id}/messages`, { content })
if (res.data.success) {
setInputValue('')
await fetchMessages(activeConvRef.current)
fetchConversations()
}
} catch (err) {
message.error(err.response?.data?.message || '发送失败')
} finally {
setSending(false)
}
}
const handleCreate = async (values) => {
setCreating(true)
try {
const payload = values.tab === 'group'
? { type: 'group', name: values.name, memberIds: values.memberIds }
: { type: 'direct', userId: values.userId }
const res = await axios.post('/api/chat/conversations', payload)
if (res.data.success) {
message.success(res.data.message)
setCreateVisible(false)
createForm.resetFields()
await fetchConversations()
// 自动打开新会话
const list = (await axios.get('/api/chat/conversations')).data
if (list.success) {
const conv = list.data.find(c => c.id === res.data.data.id)
if (conv) openConversation(conv)
}
}
} catch (err) {
message.error(err.response?.data?.message || '创建失败')
} finally {
setCreating(false)
}
}
const handleDeleteConv = async (conv) => {
try {
const res = await axios.delete(`/api/chat/conversations/${conv.id}`)
if (res.data.success) {
message.success(res.data.message)
if (activeConv?.id === conv.id) closeConversation()
fetchConversations()
}
} catch (err) {
message.error(err.response?.data?.message || '删除失败')
}
}
const canDelete = (conv) => conv.type === 'direct' || conv.creator_id === user?.id
// 群主移除群成员
const handleRemoveMember = async (memberId) => {
try {
const res = await axios.delete(`/api/chat/conversations/${activeConv.id}/members/${memberId}`)
if (res.data.success) {
message.success(res.data.message)
setMembersVisible(false)
// 刷新会话列表与当前会话
const list = await axios.get('/api/chat/conversations')
if (list.data.success) {
setConversations(list.data.data)
const conv = list.data.data.find(c => c.id === activeConv.id)
if (conv) {
setActiveConv(conv)
activeConvRef.current = conv
} else {
closeConversation()
}
}
}
} catch (err) {
message.error(err.response?.data?.message || '操作失败')
}
}
const otherOptions = allUsers.filter(u => u.id !== user?.id).map(u => ({
value: u.id,
label: (