0.0.0.4
This commit is contained in:
@@ -0,0 +1,174 @@
|
||||
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) // 每小时检查一次
|
||||
}
|
||||
Reference in New Issue
Block a user