Files
chinese-family-tree-2/lib/notifications.ts
T
freedakgmail c033e46782 0.0.0.4
2025-11-22 23:49:24 +08:00

175 lines
4.8 KiB
TypeScript

import type { FamilyMember } from "@/types/family"
/**
* 请求浏览器通知权限
*/
export async function requestNotificationPermission(): Promise<boolean> {
if (typeof window === "undefined" || !("Notification" in window)) {
console.warn("浏览器不支持通知")
return false
}
if (Notification.permission === "granted") {
return true
}
if (Notification.permission !== "denied") {
const permission = await Notification.requestPermission()
return permission === "granted"
}
return false
}
/**
* 发送浏览器通知
*/
export function sendNotification(title: string, options?: NotificationOptions) {
if (typeof window === "undefined" || !("Notification" in window)) {
return
}
if (Notification.permission === "granted") {
new Notification(title, {
icon: "/icon.svg",
badge: "/icon.svg",
...options,
})
}
}
/**
* 检查今天是否有纪念日
*/
export function checkTodayAnniversaries(members: FamilyMember[]): {
birthdays: FamilyMember[]
deathdays: FamilyMember[]
} {
const today = new Date()
const currentMonth = today.getMonth() + 1
const currentDay = today.getDate()
const birthdays: FamilyMember[] = []
const deathdays: FamilyMember[] = []
members.forEach((member) => {
// 检查生日
if (member.birthDate) {
const birthDate = new Date(member.birthDate)
if (birthDate.getMonth() + 1 === currentMonth && birthDate.getDate() === currentDay) {
birthdays.push(member)
}
}
// 检查忌日
if (member.deathDate) {
const deathDate = new Date(member.deathDate)
if (deathDate.getMonth() + 1 === currentMonth && deathDate.getDate() === currentDay) {
deathdays.push(member)
}
}
})
return { birthdays, deathdays }
}
/**
* 检查即将到来的纪念日(未来7天)
*/
export function checkUpcomingAnniversaries(members: FamilyMember[], days: number = 7): {
birthdays: Array<{ member: FamilyMember; daysUntil: number }>
deathdays: Array<{ member: FamilyMember; daysUntil: number }>
} {
const today = new Date()
const birthdays: Array<{ member: FamilyMember; daysUntil: number }> = []
const deathdays: Array<{ member: FamilyMember; daysUntil: number }> = []
members.forEach((member) => {
// 检查生日
if (member.birthDate) {
const birthDate = new Date(member.birthDate)
const thisYearBirthday = new Date(today.getFullYear(), birthDate.getMonth(), birthDate.getDate())
if (thisYearBirthday < today) {
thisYearBirthday.setFullYear(today.getFullYear() + 1)
}
const daysUntil = Math.ceil((thisYearBirthday.getTime() - today.getTime()) / (1000 * 60 * 60 * 24))
if (daysUntil > 0 && daysUntil <= days) {
birthdays.push({ member, daysUntil })
}
}
// 检查忌日
if (member.deathDate) {
const deathDate = new Date(member.deathDate)
const thisYearDeathday = new Date(today.getFullYear(), deathDate.getMonth(), deathDate.getDate())
if (thisYearDeathday < today) {
thisYearDeathday.setFullYear(today.getFullYear() + 1)
}
const daysUntil = Math.ceil((thisYearDeathday.getTime() - today.getTime()) / (1000 * 60 * 60 * 24))
if (daysUntil > 0 && daysUntil <= days) {
deathdays.push({ member, daysUntil })
}
}
})
return { birthdays, deathdays }
}
/**
* 发送今日纪念日通知
*/
export function notifyTodayAnniversaries(members: FamilyMember[]) {
const { birthdays, deathdays } = checkTodayAnniversaries(members)
if (birthdays.length > 0) {
const names = birthdays.map(m => m.fullName).join("、")
sendNotification("🎂 今日生日提醒", {
body: `今天是 ${names} 的生日!`,
tag: "birthday-today",
})
}
if (deathdays.length > 0) {
const names = deathdays.map(m => m.fullName).join("、")
sendNotification("🕯️ 今日忌日提醒", {
body: `今天是 ${names} 的忌日,缅怀先人。`,
tag: "deathday-today",
})
}
}
/**
* 设置每日通知检查
*/
export function setupDailyNotificationCheck(members: FamilyMember[]) {
if (typeof window === "undefined") {
return
}
// 检查是否已经在今天检查过
const lastCheckDate = localStorage.getItem("lastNotificationCheck")
const today = new Date().toDateString()
if (lastCheckDate !== today) {
notifyTodayAnniversaries(members)
localStorage.setItem("lastNotificationCheck", today)
}
// 设置每小时检查一次(防止用户长时间开着页面)
setInterval(() => {
const currentDate = new Date().toDateString()
const lastCheck = localStorage.getItem("lastNotificationCheck")
if (lastCheck !== currentDate) {
notifyTodayAnniversaries(members)
localStorage.setItem("lastNotificationCheck", currentDate)
}
}, 60 * 60 * 1000) // 每小时检查一次
}