最近要做一个聊天功能 以前公司是webScoket实现的聊天与推送 现在用的腾讯im
功能只有单对单在线聊天 离线推送需要购买 就不要买了 用的时候看文档吧 基本功能就是 发送消息给对方 知道对方是不是已读 别人发消息过来 告诉别人是不是已读
这次项目架构采用的是腾讯IM即时通讯 所以简单看一下 实现一下小功能
首先呢先注册登录腾讯云
文档使用时还是使用无ui的 有ui的成套的在发现问题和修改时候不太好改 而且项目ui都不同改的也麻烦
- 腾讯云地址 可以使用微信注册 然后进入个人中心实名验证一下就可以了
- 进入应用管理 如果找不到可以进入首页 搜素“即时通讯IM”点击就跳进去了
- 创建新的应用 创建完成后会有 SDKAppID和 密钥 后边项目需要使用的 因为我是自己用所以我注册的是个人用户
- 创建完成后进入 功能服务-> 账号管理 上边下拉框选择你需要的应用名称 之后点击新建账号 账号的用户名是一个唯一值 也就是在这个应用下允许搜索 添加 登录的用户 不在这个应用下是查不到用户的 还有昵称和头像链接不是必填的 这里user1 和user2就是等一下需要登录的用户
- 然后 我们基本配置就结束了接下来 我们可以下载官方提供的demo 也可以自己写demo
- 腾讯云下载中心,找到Demo源码 gitee下载 不同系统选择不同的链接 我是window的所以我跳到7的地址
- 找到web文件夹下的md文件 下边有一个相关链接 打开gitee仓库clone项目
- 下载完成后 选中vue2 或者vue3安装 启动 这里使用刚刚创建的用户 user2就会进入聊天界面 一个在线用户就创建好了
- 另一个用户 这里开始创建项目了
npm create vite@latest demo
npm install npm run dev启动
npm install @tencentcloud/chat
npm install tim-upload-plugin --save
npm i pinia // 不想用也可以自定义hooks
- 创建一个index 这里有一个config文件夹 这个文件夹需要在第8步骤的vue文件夹里 有一个debug文件夹 。chat-uikit-vue/Vue2/TUIKit/debug/。 里的所有文件
‘GenerateTestUserSig.js’ 、‘index.d.ts’、‘index.js’、‘lib-generate-test-usersig-es.min.js’
增加个添加好友和搜素用户 ---- 这个添加搜索 可以看这里的SDKapi写其他方法 这个添加 之前使用个人用户一直报错 我不确定是不是需要企业用户才能做一些别的操作 这里测试自测
main.ts
import { ref } from 'vue';
import { createPinia, defineStore } from 'pinia';
import tim from '@tencentcloud/chat';
import TIMUploadPlugin from 'tim-upload-plugin';
import { genTestUserSig } from './config/index'
export type timLoginType = { userID: string }
export type sendType = { toWHom: string, msgType?: 'text' | 'data', msgValue: any, conversationType?: 'C2C' | 'GROUP' | 'ROOM' }
export type messageType = { name: string, data: any[] }
export type searchUserId = { userId: string }
export type addFirendType = { toId: string, AddType?: 'Request' | 'Confirm', remark?: string, groupName?: string }
const win = window as any
// 添加好友参数格式
function addFirendOptionData(param: addFirendType) {
return {
wording: TIMOption.value.userID,
to: param?.toId || '',
type: param?.AddType || 'Request',
source: 'AddSource_Type_Web',
groupName: param?.groupName || '',
remark: param?.remark || ''
};
}
// 项目实例的id和key 用户必须在统一的项目管理下才会查到用户 实行方案 在注册用户时就调用接口向腾讯im管理添加用户名
export const TIMOption = ref<any>({
SDKAppID: 0,
secretKey: '',
})
export const useTIMStore = defineStore('useTIMStore', () => {
// 可发送状态
const isPrepare = ref<boolean>(false)
const onPrepare = () => {
const { TIM, CHAT } = win?.timObj
let onSdkReady = function () {
isPrepare.value = true
};
CHAT.on(TIM.EVENT.SDK_READY, onSdkReady);
}
// 初始化
const createTIM = () => {
let chat = tim.create(TIMOption.value);
chat.setLogLevel(2);
chat.registerPlugin({ 'tim-upload-plugin': TIMUploadPlugin });
win.timObj = { TIM: tim, CHAT: chat }
onPrepare()
}
// 登录
const isLogin = ref<boolean>(false)
const onLogin = async ({ userID }: timLoginType) => {
const { CHAT } = win?.timObj
const signoptions = { SDKAppID: TIMOption.value.SDKAppID, secretKey: TIMOption.value.secretKey, userID: userID }
const { userSig } = genTestUserSig(signoptions)
TIMOption.value.userID = userID
try {
TIMOption.value.userID = userID
await CHAT.login({ userID: userID, userSig: userSig });
isLogin.value = true
} catch (e) {
isLogin.value = false
}
return isLogin.value
}
// 登出
const onLogout = async () => {
try {
const { CHAT } = win?.timObj
await CHAT.logout();
isLogin.value = false
} catch { }
}
// 发送消息
const onSend = async ({ toWHom, msgType = 'text', msgValue, conversationType = 'C2C' }: sendType) => {
if (isPrepare.value) {
if (!msgValue) {
return { code: 99999, message: '不能是空', data: null, problem: 'customLog-onSend::: 空值' }
}
const { CHAT } = win?.timObj
let res = null
console.log(msgType);
if (msgType === 'data') {
let message = CHAT.createCustomMessage({
to: toWHom,
conversationType: conversationType,
payload: {
[msgType]: JSON.stringify(msgValue),
description: '自定义消息说明',
extension: ''
}
});
res = await CHAT.sendMessage(message)
}
if (msgType === 'text') {
let message = CHAT.createTextMessage({
to: toWHom,
conversationType: conversationType,
payload: { [msgType]: msgValue }
});
res = await CHAT.sendMessage(message)
}
if (res?.code === 0) {
return res
} else {
return false
}
} else {
return false
}
}
// 发送消息对方已阅
const onMessageRead = (callback: Function) => {
const { TIM, CHAT } = win?.timObj
if (callback && typeof callback === 'function') {
const onMessageReadByPeer = function (e: messageType) {
callback(e?.data || [])
};
CHAT.on(TIM.EVENT.MESSAGE_READ_BY_PEER, onMessageReadByPeer);
return true
} else {
return false
}
}
// 接收消息
const onMessage = (callback: Function) => {
const { TIM, CHAT } = win?.timObj
if (callback && typeof callback === 'function') {
let onMessageReceived = function (e: messageType) {
callback(e?.data || [])
};
CHAT.on(TIM.EVENT.MESSAGE_RECEIVED, onMessageReceived);
return true
} else {
return false
}
}
// 接收消息返回已阅
const onReceipt = (item: any) => {
const { CHAT } = win?.timObj;
const msg = { conversationID: item.conversationID, messageID: item.ID };
CHAT.setMessageRead(msg)
}
// 搜索用户
const onSearchUser = async ({ userId }: searchUserId) => {
const { CHAT } = win.timObj
try {
const { data } = await CHAT.getUserProfile({ userIDList: [userId] })
return data
} catch (e) {
return []
}
}
// 申请添加好友
const onAddFirend = async ({ toId }: addFirendType) => {
const { CHAT } = win.timObj
try {
const param = addFirendOptionData({ toId: toId, AddType: 'Request' })
const { data } = await CHAT.addFriend(param)
return data
} catch (e) {
return false
}
}
// 确认添加好友
const onConfirmAddFirend = async ({ userId }: searchUserId) => {
const { CHAT } = win.timObj
try {
const param = addFirendOptionData({ toId: userId, AddType: 'Confirm' })
const { data } = await CHAT.addFriend(param)
return data
} catch (e) {
return false
}
}
// 查询好友列表
const onSearchFirendList = async () => {
const { CHAT } = win.timObj
try {
const res = await CHAT.getFriendList()
return res?.data
} catch {
return []
}
}
return {
TIMOption,
isPrepare,
createTIM,
onLogin,
onLogout,
onSend,
onMessage,
onReceipt,
onMessageRead,
onSearchFirendList,
onAddFirend,
onConfirmAddFirend,
onSearchUser
}
})
export {
createPinia
}
vue文件 简单看一下效果 这里登录就是user1了
登录传入username 调用index里的 GenerateTestUserSig.js 里抛出的genTestUserSig方法返回sig值 然后进行登录
<template>
<div style="width: 100%;height:100%">
<!-- 登录 -->
<div><input type="text" v-model="username"><button @click="login">login</button></div>
<!-- 搜索用户信息 -->
<div><span>搜索用户:</span>{{ searchUserData?.nick }} <span v-if="searchUserData?.nick" @click="addFirend">添加</span>
</div>
<div style="display: flex;">
<div style="flex: 1;border: 1px solid #000;">
<!-- 搜索用户 -->
<div style="border: 1px solid #000;">
<input type="text" v-model="firendValue"> <span @click="handlAddFirend">搜索</span>
</div>
<div>
<!-- 好友列表 -->
<div>好友</div>
<div v-for="(item, index) in firendList" :key="index">
<div v-html="item"></div>
</div>
</div>
</div>
<div style="flex: 2;">
<div style="height: 200px;overflow-y: auto; display: flex; border: 1px solid #000;">
<!-- 消息信息 -->
<div v-for="(item, index) in list" :key="index">
{{ JSON.stringify(item) }}
</div>
</div>
<!-- 发送 -->
<div style="display: flex; border: 1px solid #000;">
<input style="flex:1" type="text" v-model="mesValue">
<span @click="send">send</span>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { useTIMStore, type messageType } from './index'
const TIMStore = useTIMStore()
const username = ref<string>('user1039' || 'user1') // 本人用户名
const firendValue = ref<string>("user1011" || 'user1') // 添加好友的用户名
const firendList = ref<any>([]) // 好友列表
const mesValue = ref<string>('') // 发送的消息
const list = ref<any>([]) // 消息列表
const searchUserData = ref<any>({}) // 搜索用户结果
const login = async () => {
const res = await TIMStore.onLogin({ userID: username.value })
if (res) {
setTimeout(async () => {
firendList.value = await TIMStore.onSearchFirendList()
}, 100);
}
}
login()
// 接收消息
TIMStore.onMessage((e: messageType['data']) => {
list.value.push(e[0].payload.text)
setTimeout(() => {
// 发送我已阅读
TIMStore.onReceipt(e[0])
}, 1000);
})
// 接收已经对方阅读的消息
TIMStore.onMessageRead(() => {
})
// 发送
const send = async () => {
const { data }: any = await TIMStore.onSend({ toWHom: '', msgType: 'text', msgValue: mesValue.value })
list.value.push(data?.message?.payload.text)
}
// 查找用户
const handlAddFirend = async () => {
const res = await TIMStore.onSearchUser({ userId: firendValue.value })
searchUserData.value = res?.[0]
}
// 添加
const addFirend = async () => {
const res = await TIMStore.onAddFirend({ toId: searchUserData.value?.userID })
}
</script>
<style scoped></style>