@wangxi-pro/im
v1.0.2
Published
Vue3 WebSocket 即时通讯插件,微信风格设计,支持完善的连接管理、可自定义的聊天界面和智能滚动,同时适配 H5 和 PC 端
Maintainers
Readme
@wangxi-pro/im
Vue3 WebSocket 即时通讯插件,微信风格设计,支持完善的连接管理、可自定义的聊天界面和智能滚动机制。同时适配 H5 移动端和 PC 端。

✨ 特性
- 🚀 开箱即用 - 简单配置即可使用
- 💬 微信风格 - 完美复刻微信的消息布局和交互体验
- 左右消息气泡区分
- 气泡宽度自适应(最大70%)
- 底部功能面板滑入动画
- 智能发送按钮切换
- 🔄 自动重连 - 断线自动重连,支持指数退避算法
- ❤️ 心跳检测 - 可自定义心跳间隔和超时时间
- 📦 消息队列 - 离线消息缓存,连接后自动发送
- 🎨 高度自定义 - 支持自定义样式、插槽和配置
- 📱 响应式设计 - 完美适配 H5 和 PC 端
- 🎯 智能滚动 - 新消息自动滚动,手动滚动后自动禁用
- 📌 TypeScript - 完整的类型定义
- 🎭 多消息类型 - 支持文本、图片、视频、语音、文件、位置、链接等
📦 安装
npm install @wangxi-pro/im或
yarn add @wangxi-pro/im或
pnpm add @wangxi-pro/im🚀 快速开始
全局注册
import { createApp } from 'vue'
import IMPlugin from '@wangxi-pro/im'
import '@wangxi-pro/im/dist/style.css'
const app = createApp(App)
app.use(IMPlugin)
app.mount('#app')按需引入
<template>
<div class="chat-wrapper">
<ChatContainer
:messages="messages"
:is-loading="isLoading"
:loading-text="'连接中...'"
@send="handleSend"
@retry="handleRetry"
@load-history="handleLoadHistory"
@tool-click="handleToolClick"
>
<template #header>
<div class="chat-header">智能助手</div>
</template>
</ChatContainer>
</div>
</template>
<script setup lang="ts">
import { ChatContainer, useWebSocket, MessageType } from '@wangxi-pro/im'
import '@wangxi-pro/im/dist/style.css'
// 初始化 WebSocket
const { messages, isLoading, connect, send, resend } = useWebSocket({
url: 'ws://your-server.com/ws',
heartbeatInterval: 30000,
heartbeatTimeout: 45000
})
// 连接
connect()
// 发送消息
const handleSend = async (text: string) => {
await send({
type: MessageType.TEXT,
content: { text },
sender: {
id: 'user',
name: '我',
avatar: 'https://example.com/avatar.jpg'
},
position: 'right' // 自己发送的消息在右侧
})
}
// 处理工具栏点击
const handleToolClick = (type: string) => {
console.log('点击了工具:', type)
// 处理图片上传、拍摄等逻辑
}
// 加载历史消息
const handleLoadHistory = () => {
// 加载更多消息逻辑
}
</script>
<style>
.chat-wrapper {
height: 100vh;
display: flex;
flex-direction: column;
}
.chat-header {
height: 44px;
display: flex;
align-items: center;
justify-content: center;
background: #ededed;
font-weight: bold;
}
</style>📖 核心功能详解
1. 微信风格输入区域
插件内置了高度还原微信的输入区域:
- 语音/键盘切换:左侧按钮一键切换输入模式
- 表情面板:内置常用表情,支持点击插入
- 功能面板:点击 "+" 号滑出,包含图片、拍摄、视频、文件等常用功能
- 智能发送按钮:输入框有内容时 "+" 号自动变为 "发送" 按钮
2. 消息气泡布局
- 左右区分:通过
position: 'left' | 'right'属性控制消息显示位置 - 宽度自适应:气泡宽度根据内容自适应,最大不超过屏幕宽度的 70%
- 样式还原:精准还原微信气泡的圆角、颜色(右侧 #95EC69)和阴影细节
3. 智能滚动机制
- 自动滚动:收到新消息时自动滚动到底部
- 手动暂停:用户向上滚动查看历史消息时,自动暂停新消息滚动
- 回到底部:当有未读新消息且处于历史位置时,显示"回到底部"按钮
4. 高级自定义输入区域
插件提供了多个插槽,允许你完全控制输入区域的布局和功能:
- input-bar:替换整个输入栏
- input-left:自定义左侧按钮(如语音切换)
- input-field:自定义输入框
- input-right:自定义右侧按钮(如表情、发送)
<ChatContainer>
<!-- 自定义左侧按钮 -->
<template #input-left="{ isVoiceMode, toggleVoiceMode }">
<button @click="toggleVoiceMode">
{{ isVoiceMode ? '键盘' : '语音' }}
</button>
</template>
<!-- 自定义右侧按钮 -->
<template #input-right="{ handleSend, canSend }">
<button
class="custom-send-btn"
:disabled="!canSend"
@click="handleSend"
>
发送
</button>
</template>
</ChatContainer>📚 API 文档
useWebSocket
WebSocket 管理的组合式 API。
参数 (WebSocketConfig):
| 属性 | 类型 | 默认值 | 说明 | |------|------|--------|------| | url | string | - | WebSocket 服务器地址 | | reconnect | boolean | true | 是否启用自动重连 | | maxReconnectAttempts | number | 5 | 最大重连次数 | | reconnectInterval | number | 1000 | 初始重连间隔(ms) | | heartbeat | boolean | true | 是否启用心跳 | | heartbeatInterval | number | 30000 | 心跳间隔(ms) | | messageQueueSize | number | 100 | 离线消息队列大小 |
返回值:
{
status: Ref<ConnectionStatus> // 连接状态
messages: Ref<Message[]> // 消息列表
isLoading: Ref<boolean> // 是否正在重连
isConnected: Ref<boolean> // 是否已连接
connect: () => void // 连接方法
disconnect: () => void // 断开连接方法
send: (message) => Promise<void> // 发送消息方法
resend: (messageId) => Promise<void> // 重发消息方法
}ChatContainer 组件
Props:
| 属性 | 类型 | 默认值 | 说明 | |------|------|--------|------| | messages | Message[] | [] | 消息列表 | | isLoading | boolean | false | 是否显示 loading | | loadingText | string | '重连中...' | loading 文本 | | showInput | boolean | true | 是否显示输入框 | | enableHistory | boolean | false | 是否启用下拉加载历史 | | isHistoryLoading | boolean | false | 历史消息加载状态 | | bubbleConfig | MessageBubbleConfig | - | 气泡样式配置 |
Events:
| 事件 | 参数 | 说明 | |------|------|------| | send | (text: string) | 发送文本消息 | | tool-click | (type: string) | 点击工具栏图标 (image, camera, file...) | | load-history | - | 触发加载历史消息 | | retry | (messageId: string) | 点击重发按钮 |
Slots:
| 插槽名 | 参数 | 说明 | |--------|------|------| | header | - | 顶部自定义内容 | | footer | - | 底部自定义内容 | | input-bar | - | 替换整个输入栏 | | input-left | { isVoiceMode, toggleVoiceMode } | 自定义输入栏左侧 | | input-field | { isVoiceMode, inputText, handleInput } | 自定义输入框区域 | | input-right | { toggleEmojiPanel, toggleToolPanel, handleSend, canSend } | 自定义输入栏右侧 | | tool-panel | - | 自定义功能面板内容 | | emoji-panel | - | 自定义表情面板内容 |
MessageBubble 组件
Props:
| 属性 | 类型 | 说明 | |------|------|------| | message | Message | 消息对象 | | config | MessageBubbleConfig | 样式配置 |
Slots:
| 插槽名 | 参数 | 说明 | |--------|------|------| | avatar | { sender } | 自定义头像 | | content-{type} | { message } | 自定义特定类型消息内容 |
💡 消息类型结构
文本消息 (TEXT)
{
type: 'text',
content: { text: '你好' }
}图片消息 (IMAGE)
{
type: 'image',
content: {
url: 'https://...',
thumbnail: 'https://...', // 缩略图
width: 800,
height: 600
}
}文件消息 (FILE)
{
type: 'file',
content: {
url: 'https://...',
name: '文档.pdf',
size: 102400,
type: 'application/pdf'
}
}🔧 开发与构建
# 安装依赖
npm install
# 启动开发服务器(Demo)
npm run dev
# 构建库
npm run build
# 类型检查
npm run type-check📄 License
MIT
🤝 贡献
欢迎提交 Issue 和 Pull Request!
Made with ❤️ by wangxi-pro
