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

如何在SwiftUI中实现基于Contentful的通知徽章与公告中心功能

嘿,这个需求我之前帮朋友做过类似的,拆解成几个核心模块就好实现了,我给你一步步梳理:

核心实现思路拆解

1. 从Contentful拉取公告数据

首先得用Contentful的官方SDK来获取公告内容,建议按发布时间倒序拉取,方便后续计算未读数量。假设你的公告内容类型ID是announcement,代码示例如下:

// 初始化Contentful客户端
const client = contentful.createClient({
  space: '你的Space ID',
  accessToken: '你的访问令牌'
});

// 获取所有公告,按发布时间从新到旧排序
async function fetchAnnouncements() {
  try {
    const response = await client.getEntries({
      content_type: 'announcement',
      order: '-fields.publishedDate'
    });
    return response.items;
  } catch (error) {
    console.error('拉取公告失败:', error);
    return [];
  }
}

2. 计算未读数量并更新铃铛徽章

要实现徽章计数,关键是记录用户最后查看公告的时间,这里用localStorage做本地持久化(如果有用户系统,存在后端数据库会更可靠)。每次拉取公告时,对比发布时间和用户最后查看时间,统计未读数量:

// 获取未读公告数量
async function getUnreadCount() {
  const announcements = await fetchAnnouncements();
  // 从本地存储获取最后查看时间,默认设为0(代表从未查看)
  const lastViewedTime = localStorage.getItem('lastAnnouncementViewTime') || 0;
  
  return announcements.filter(announcement => {
    const publishTimestamp = new Date(announcement.fields.publishedDate).getTime();
    return publishTimestamp > parseInt(lastViewedTime);
  }).length;
}

// 更新铃铛徽章显示
async function updateNotificationBadge() {
  const badge = document.getElementById('notification-badge');
  const unreadCount = await getUnreadCount();
  
  if (unreadCount > 0) {
    badge.textContent = unreadCount;
    badge.style.display = 'inline-block'; // 显示徽章
  } else {
    badge.style.display = 'none'; // 隐藏徽章
  }
}

// 页面加载时自动更新徽章
window.addEventListener('load', updateNotificationBadge);

3. 点击铃铛弹出公告视图并标记已读

点击铃铛时,弹出公告列表,同时把当前时间记录为用户最后查看时间,这样下次计算未读时就会把之前的公告标记为已读:

const bellIcon = document.getElementById('bell-icon');
const announcementModal = document.getElementById('announcement-modal');
const announcementList = document.getElementById('announcement-list');

// 点击铃铛触发弹窗
bellIcon.addEventListener('click', async () => {
  // 显示公告弹窗
  announcementModal.style.display = 'block';
  // 渲染公告列表
  const announcements = await fetchAnnouncements();
  renderAnnouncementList(announcements);
  
  // 记录当前时间为最后查看时间,标记所有公告为已读
  localStorage.setItem('lastAnnouncementViewTime', Date.now().toString());
  // 更新徽章(此时应该隐藏)
  updateNotificationBadge();
});

// 渲染公告列表的函数
function renderAnnouncementList(announcements) {
  announcementList.innerHTML = announcements.map(item => `
    <div class="announcement-item">
      <h4>${item.fields.title}</h4>
      <p>${item.fields.content}</p>
      <small>${new Date(item.fields.publishedDate).toLocaleString()}</small>
    </div>
  `).join('');
}

// 关闭弹窗的逻辑(点击关闭按钮或遮罩层)
document.getElementById('close-modal-btn').addEventListener('click', () => {
  announcementModal.style.display = 'none';
});

4. 额外优化建议

  • 定时刷新:可以设置定时器(比如每5分钟)自动拉取公告并更新徽章,不用用户手动刷新页面;
  • 已读/未读样式区分:在公告列表里给未读公告加特殊样式(比如加粗背景色),提升用户体验;
  • 后端同步:如果有用户系统,把最后查看时间存在后端,这样用户换设备也能同步未读状态;
  • 分页加载:如果公告数量多,用Contentful的分页API分批拉取,避免一次性加载过多数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 19:02:32