当前位置: 首页 > news >正文

Ruoyi若依轮询通知公告实战:从零构建前端消息铃铛组件

1. 项目背景与需求分析在开发企业级后台管理系统时实时消息通知是个刚需功能。就拿我们常见的后台管理系统来说管理员需要第一时间知道系统公告、待办任务或者审批提醒。传统做法是让用户手动刷新页面查看新消息这体验实在太糟糕了。我在实际项目中就遇到过这种情况用户总是抱怨为什么不能自动弹出新消息提醒。Ruoyi框架本身提供了完善的通知公告模块但默认需要用户主动点击才能查看。我们需要在前端导航栏添加一个会呼吸的铃铛图标当有新消息时自动闪烁提醒点击后跳转到公告页面。这个需求看似简单但实现时要注意几个关键点首先消息获取要用轮询方式定期检查服务端每5秒一次。虽然WebSocket更高效但很多传统项目环境不支持或者运维不愿意开放新端口。其次必须处理好组件生命周期避免切换路由时内存泄漏。最后动画效果要醒目但不刺眼我见过有项目用大红底色闪烁用户反馈差点被闪瞎眼。2. 环境准备与基础集成2.1 初始化Ruoyi-Vue项目确保你已经搭建好Ruoyi-Vue开发环境。我这里用的是4.7.5版本Node.js版本16.x。如果还没初始化项目可以执行git clone https://gitee.com/y_project/RuoYi-Vue.git cd RuoYi-Vue npm install关键依赖需要检查vue 2.6.xelement-ui 2.15.xaxios 0.21.x2.2 分析现有通知接口Ruoyi后端已经提供了通知公告的API接口我们打开src/api/system/notice.js可以看到export function listNotice(query) { return request({ url: /system/notice/list, method: get, params: query }) }这个接口返回的数据结构是这样的{ code: 200, msg: success, total: 5, rows: [...] }我们主要关注total字段表示未读消息数量。测试接口是否通畅可以用Postman发送GET请求到/system/notice/list应该能看到测试数据。3. 核心功能实现3.1 修改导航栏组件找到src/layout/components/Navbar.vue在script部分新增数据定义data() { return { noticeContent: 暂无新消息, noticeCount: 0, pollInterval: null, pollDelay: 5000 // 5秒轮询间隔 } }3.2 实现轮询机制在methods中添加核心方法methods: { // 启动轮询 startPolling() { // 先立即执行一次 this.fetchNotices() // 设置定时器 this.pollInterval setInterval(() { this.fetchNotices() }, this.pollDelay) }, // 停止轮询 stopPolling() { if (this.pollInterval) { clearInterval(this.pollInterval) this.pollInterval null } }, // 获取通知数据 async fetchNotices() { try { const res await listNotice() this.noticeCount res.total this.noticeContent res.total 0 ? 您有${res.total}条未读消息 : 暂无新消息 } catch (error) { console.error(获取通知失败:, error) } } }3.3 生命周期管理在Vue生命周期钩子中控制轮询created() { this.startPolling() }, beforeDestroy() { this.stopPolling() }这里有个坑我踩过如果只在mounted中启动轮询在keep-alive组件切换时可能不会正确销毁定时器。所以最好在created/beforeDestroy这对钩子中处理。4. UI效果优化4.1 添加铃铛图标在导航栏模板部分添加这个结构放在right-menu区域内el-tooltip :contentnoticeContent placementbottom el-badge :valuenoticeCount :hiddennoticeCount 0 classnotice-badge i classel-icon-bell clicktoNoticePage/i /el-badge /el-tooltip4.2 实现呼吸动画在style部分添加这些样式.notice-badge { margin-right: 15px; cursor: pointer; /deep/ .el-badge__content { top: 12px; right: 5px; transform: scale(0.9); transition: all 0.3s; } .has-notice { /deep/ .el-icon-bell { animation: breathe 1.5s infinite ease-in-out; } /deep/ .el-badge__content { background-color: #f56c6c; box-shadow: 0 0 0 2px #fff; } } } keyframes breathe { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.2); } }注意这里用了深度选择器/deep/来覆盖element-ui默认样式。动画效果是铃铛图标会周期性放大缩小类似呼吸效果比单纯闪烁更优雅。5. 性能优化与异常处理5.1 节流控制频繁轮询可能造成服务器压力我们可以优化fetchNotices方法async fetchNotices() { // 如果已有请求在进行则跳过 if (this.isPolling) return this.isPolling true try { const res await listNotice({ pageNum: 1, pageSize: 5, status: 0 // 只查询未读 }) // 只有当数据变化时才更新视图 if (res.total ! this.noticeCount) { this.noticeCount res.total this.noticeContent res.total 0 ? 您有${res.total}条未读消息 : 暂无新消息 } } finally { this.isPolling false } }5.2 网络异常处理真实项目中网络可能不稳定需要增强健壮性async fetchNotices() { // ...省略前面的节流逻辑 try { const res await listNotice().timeout(3000) // 3秒超时 // ...处理数据 } catch (err) { if (err.code ECONNABORTED) { console.warn(请求超时下次重试) } else if (err.response?.status 401) { this.stopPolling() this.$message.error(登录已过期) } else { console.error(通知获取异常:, err) // 指数退避重试 this.pollDelay Math.min(this.pollDelay * 2, 60000) } } }建议添加axios的timeout拦截器// 在src/utils/request.js中添加 axios.interceptors.request.use(config { config.timeout 3000 return config })6. 实际应用中的经验分享在电商后台项目中我们给这个铃铛组件加了这些增强功能分级提醒根据消息类型显示不同颜色普通通知蓝色徽章预警消息橙色徽章紧急告警红色徽章持续震动本地缓存用localStorage存储最后一次获取的消息数避免页面刷新时闪烁// 在fetchNotices成功回调中添加 localStorage.setItem(lastNoticeCount, res.total) // 在data初始化时读取 data() { return { noticeCount: parseInt(localStorage.getItem(lastNoticeCount)) || 0 } }声音提醒需要用户授权playNotificationSound() { const audio new Audio(/static/sound/notification.mp3) audio.volume 0.3 audio.play().catch(e console.log(播放失败:, e)) }在团队协作工具中我们还实现了这些功能点击铃铛后自动标记为已读下拉展示最近5条消息摘要移动端适配使用rem单位有个坑要注意Safari浏览器对音频自动播放有限制必须要在用户交互事件如click中首次触发音频播放之后才能用代码控制。
http://www.zskr.cn/news/1310531.html

相关文章:

  • 2026年武汉办公室空调深度测评:如何为你的办公空间匹配最佳方案? - 速递信息
  • 终极指南:如何在Windows电脑上实现AirPlay 2无线投屏功能
  • 2026年全国人力资源咨询公司哪家好 专注落地服务 口碑良好的专业服务机构 - 深度智识库
  • MASA模组汉化包终极指南:快速解决Minecraft英文界面问题
  • 抖音无水印下载技术解密:构建高性能分布式内容采集系统
  • 【简单】一行代码求两个数的最大公约数-Java
  • 【电影研究者的AI护城河】:NotebookLM深度定制教程——仅限高校影视实验室内部流传的6大高阶技巧
  • IR 召回评测基准(英文数据集)——MS MARCO 实战指南
  • 为什么92%的团队在2026年前仓促重构AI栈?——主流框架弃用预警、许可证变更清单与平滑迁移路线图
  • 小微创业团队如何利用Taotoken Token Plan控制AI开发成本
  • WinFlexBison:Windows平台词法分析与语法生成工具的终极解决方案
  • 在Windows上安装APK的完整指南:告别模拟器,拥抱原生体验
  • 【困难】丟棋子问题-Java:解法五
  • 别再只用MATLAB了!用Mathematica 13.3/14.0做科研计算,这些隐藏技巧让你效率翻倍
  • Windows终极优化神器:WinUtil高效自动化管理指南
  • 15分钟零基础教程:AI语音克隆与声音转换完全指南
  • 【效率革命】3dMax UV-Packer:告别手动,拥抱智能UV布局新时代
  • 单卡训练mmsegmentation模型?先把这个SyncBN改成BN(附完整配置文件修改指南)
  • 首驱电动车和雅迪、台铃质量真实差距:日常通勤到底怎么选? - 速递信息
  • Cursor Pro免费激活终极指南:10步解锁AI编程助手完整功能
  • 硬件工程师必看:SMT贴片厂实地探访,从钢网到回流焊的完整避坑指南
  • 2026 最新版 Kali Linux 保姆级安装教程!零基础从装机到实战全程精讲,小白轻松入门精通
  • 告别DLL地狱:TensorFlow 2.10降级后缺失cudart64_101.dll等文件的三种修复实战
  • STM32 GPIO八种模式详解:从硬件原理到实战配置
  • Ubuntu 18.04.6 从零到一:新手避坑与高效配置实战指南
  • CVAT 实战指南:从界面布局到高效标注全解析
  • SecureCRT 9.1.0不止是安装:揭秘高级功能如会话日志、脚本自动化与安全配置最佳实践
  • 【困难】画匠问题-Java:解法一
  • 上万家资本资源背书:融资信息平台怎么选不踩坑 - 速递信息
  • KMS_VL_ALL_AIO终极激活指南:3分钟免费激活Windows和Office的完整教程