在即时通讯场景中,群公告是信息同步的重要渠道。本文将基于uniapp框架,结合腾讯云IM SDK,详细讲解如何实现群公告的发布、修改、历史记录查询等核心功能。
SDKAppID
并生成密钥对(生产环境建议后端生成UserSig)# 创建UniApp项目(若已创建可跳过)
vue create -p dcloudio/uni-preset-vue im-group-notice
# 安装依赖
npm install tim-wx-sdk dayjs --save
// utils/tim.js
import TIM from 'tim-wx-sdk'
export const createTIM = () => {
const options = {
SDKAppID: xxxxxxxxxxx, // 替换为实际ID
group: {
// 开启群组资料变更监听
onGetGroupInfo: true,
onUpdateGroupInfo: true
}
}
#ifdef H5
options.useUploadPlugin = true
#endif
const tim = TIM.create(options)
// 监听群资料变更
tim.on(TIM.EVENT.GROUP_ATTRIBUTES_UPDATE, handleGroupUpdate)
return tim
}
// 群公告数据结构规范
const NOTICE_SCHEMA = {
content: '', // 公告内容(支持Markdown)
publisher: '', // 发布者ID
publishTime: 0, // 发布时间戳
version: 1 // 版本号(用于冲突检测)
}
// api/group.js
export const updateGroupNotice = async (groupID, newContent) => {
try {
// 1. 获取当前群资料
const { data: currentProfile } = await tim.getGroupProfile({ groupID })
// 2. 构造新公告数据
const newNotice = {
...NOTICE_SCHEMA,
content: newContent,
publisher: tim.userID,
publishTime: Date.now(),
version: (currentProfile.group.notification?.version || 0) + 1
}
// 3. 更新群资料
const promise = tim.setGroupProfile({
groupID,
notification: JSON.stringify(newNotice)
})
// 4. 发送系统通知
await sendNoticeUpdateNotification(groupID, newNotice)
return await promise
} catch (error) {
handleTIMError(error, '更新公告')
}
}
// utils/permission.js
export const checkNoticePermission = async (groupID) => {
// 获取群组资料
const { data: groupProfile } = await tim.getGroupProfile({ groupID })
// 校验规则
const rules = [
{
check: () => groupProfile.group.ownerID === tim.userID,
error: '仅群主可操作'
},
{
check: () => groupProfile.group.type === 'Public',
error: '私有群暂不支持'
}
]
for (const rule of rules) {
if (!rule.check()) {
uni.showToast({ title: rule.error, icon: 'none' })
return false
}
}
return true
}
// 监听群资料变更
const handleGroupUpdate = (event) => {
if (event.data.groupID !== currentGroupID) return
try {
const newNotice = JSON.parse(event.data.notification)
renderNotice(newNotice)
} catch (error) {
console.error('公告解析失败', error)
}
}
// 富文本渲染
const renderNotice = (notice) => {
const htmlContent = marked.parse(notice.content)
// H5使用v-html,小程序使用rich-text组件
#ifdef H5
noticeRef.value.innerHTML = htmlContent
#endif
#ifdef MP-WEIXIN
WxParse.wxParse('notice', 'html', htmlContent, that, 5)
#endif
}
export const sendNoticeUpdateNotification = async (groupID, notice) => {
const message = tim.createCustomMessage({
to: groupID,
conversationType: TIM.TYPES.CONV_GROUP,
payload: {
data: JSON.stringify({
type: 'GROUP_NOTICE_UPDATE',
content: notice.content,
publisher: notice.publisher,
time: notice.publishTime
})
}
})
return tim.sendMessage(message)
}
// 注册消息监听
tim.on(TIM.EVENT.MESSAGE_RECEIVED, (event) => {
event.data.forEach(message => {
if (message.type === 'TIMCustomMessage') {
try {
const data = JSON.parse(message.payload.data)
if (data.type === 'GROUP_NOTICE_UPDATE') {
handleNoticeUpdate(data)
}
} catch (error) {
console.error('消息解析失败', error)
}
}
})
})
const handleNoticeUpdate = (data) => {
uni.showToast({
title: `新公告:${data.content.slice(0, 10)}...`,
icon: 'none'
})
// 更新本地公告缓存
updateLocalNoticeCache(data)
}
export const getNoticeHistory = async (groupID) => {
// 实际开发需对接后端接口
// 示例返回模拟数据
return [
{ version: 1, content: '初始公告', time: 1620000000000 },
{ version: 2, content: '更新说明', time: 1620003600000 }
]
}
// 使用dayjs处理时间
import dayjs from 'dayjs'
export const scheduleNotice = (groupID, content, publishTime) => {
const timer = setTimeout(async () => {
await updateGroupNotice(groupID, content)
uni.showToast({ title: '公告已发布' })
}, dayjs(publishTime).diff(dayjs()))
return () => clearTimeout(timer) // 返回取消函数
}
安全建议:
性能优化:
uni.setStorageSync
)version
字段)异常处理:
const handleTIMError = (error, action) => {
const errMap = {
10025: '无操作权限',
20003: '群不存在',
20013: '参数错误',
20020: '版本冲突'
}
const msg = errMap[error.code] || error.message
uni.showToast({ title: `${action}失败:${msg}`, icon: 'none' })
}
通过本文实现,你可以获得:
实际开发中建议: