175 lines
4.8 KiB
TypeScript
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) // 每小时检查一次
|
|
}
|