You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular中通知徽标计数管理方案咨询

技术方案:Angular通知面板计数更新(无WebSocket)

一、后端层设计(数据库+API)

  • 通知表新增is_read布尔字段,默认值为false,用于标记通知是否已读
  • 提供3个核心API接口:
    • GET /api/notifications/unread-count:返回当前用户未读通知总数,用于快速更新徽标
    • GET /api/notifications:获取当前用户通知列表,支持?unread=true参数筛选未读通知
    • PUT /api/notifications/mark-read:批量标记通知为已读,支持传ids数组指定单个通知,或传all=true标记所有未读通知

二、Angular前端实现

1. 封装通知服务

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';

@Injectable({ providedIn: 'root' })
export class NotificationService {
  constructor(private http: HttpClient) {}

  // 获取未读计数
  getUnreadCount(): Observable<number> {
    return this.http.get<number>('/api/notifications/unread-count');
  }

  // 获取通知列表
  getNotifications(unreadOnly = false): Observable<any[]> {
    return this.http.get<any[]>(`/api/notifications?unread=${unreadOnly}`);
  }

  // 标记通知为已读
  markAsRead(notificationIds?: number[], markAll = false): Observable<void> {
    const payload = notificationIds ? { ids: notificationIds } : { all: markAll };
    return this.http.put<void>('/api/notifications/mark-read', payload);
  }
}

2. 通知面板组件逻辑

import { Component, OnInit } from '@angular/core';
import { NotificationService } from './notification.service';

@Component({
  selector: 'app-notification-panel',
  templateUrl: './notification-panel.component.html',
  styleUrls: ['./notification-panel.component.css']
})
export class NotificationPanelComponent implements OnInit {
  unreadCount = 0;
  notifications: any[] = [];
  panelOpen = false;

  constructor(private notificationService: NotificationService) {}

  ngOnInit(): void {
    this.loadUnreadCount();
  }

  // 加载未读计数
  loadUnreadCount(): void {
    this.notificationService.getUnreadCount().subscribe(count => {
      this.unreadCount = count;
    });
  }

  // 打开通知面板
  openPanel(): void {
    this.panelOpen = true;
    // 获取通知列表并标记所有未读为已读
    this.notificationService.getNotifications(true).subscribe(unReads => {
      const ids = unReads.map(n => n.id);
      this.notificationService.markAsRead(ids).subscribe(() => {
        this.loadUnreadCount();
      });
    });
    // 拉取全量通知展示
    this.notificationService.getNotifications().subscribe(notifications => {
      this.notifications = notifications;
    });
  }

  // 单个通知标记已读
  markSingleRead(notificationId: number): void {
    this.notificationService.markAsRead([notificationId]).subscribe(() => {
      this.loadUnreadCount();
      // 本地更新状态,避免重复请求
      const target = this.notifications.find(n => n.id === notificationId);
      if (target) target.is_read = true;
    });
  }
}

3. 徽标样式与模板

CSS样式:

.notification-icon {
  position: relative;
  cursor: pointer;
}

.notification-badge {
  position: absolute;
  top: -6px;
  right: -6px;
  background: #ff4d4f;
  color: #fff;
  border-radius: 50%;
  width: 18px;
  height: 18px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 11px;
  display: none;
}

.notification-badge.show {
  display: flex;
}

.notification-item.unread {
  background-color: #f5f5f5;
  font-weight: 500;
}

组件模板:

<div class="notification-icon" (click)="openPanel()">
  <i class="fa fa-bell"></i>
  <span class="notification-badge" [class.show]="unreadCount > 0">{{ unreadCount }}</span>
</div>

<div class="notification-panel" *ngIf="panelOpen">
  <div *ngFor="let item of notifications" 
       class="notification-item"
       [class.unread]="!item.is_read"
       (click)="markSingleRead(item.id)">
    {{ item.title }}
    <p>{{ item.content }}</p>
  </div>
</div>

三、优化建议

  • 定时刷新:在通知服务中添加定时器(比如每30秒)调用getUnreadCount,提升计数实时性
  • 本地缓存:将未读计数存入localStorage,标记已读后同步更新缓存,减少不必要的API请求
  • 请求防抖:如果用户频繁操作面板,对标记已读的请求做防抖处理,避免重复提交

内容的提问来源于stack exchange,提问作者JSLover

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 20:09:23