feat: 添加推送通知功能,支持订阅和发送通知
This commit is contained in:
@@ -79,12 +79,15 @@ const updateTheme = () => {
|
||||
let mediaQuery
|
||||
onMounted(() => {
|
||||
updateTheme()
|
||||
messageStore.updateUnreadCount()
|
||||
mediaQuery = window.matchMedia('(prefers-color-scheme: dark)')
|
||||
mediaQuery.addEventListener('change', updateTheme)
|
||||
setActive(route.path)
|
||||
})
|
||||
|
||||
setInterval(() => {
|
||||
messageStore.updateUnreadCount()
|
||||
}, 30 * 1000) // 每30秒更新一次未读消息数
|
||||
|
||||
// 监听路由变化调整
|
||||
watch(() => route.path, (newPath) => {
|
||||
setActive(newPath)
|
||||
@@ -127,6 +130,48 @@ const handleAddTransactionSuccess = () => {
|
||||
window.dispatchEvent(event)
|
||||
}
|
||||
|
||||
// 辅助函数:将 Base64 字符串转换为 Uint8Array
|
||||
const urlBase64ToUint8Array = (base64String) => {
|
||||
const padding = '='.repeat((4 - base64String.length % 4) % 4);
|
||||
const base64 = (base64String + padding).replace(/-/g, '+').replace(/_/g, '/');
|
||||
const rawData = window.atob(base64);
|
||||
const outputArray = new Uint8Array(rawData.length);
|
||||
for (let i = 0; i < rawData.length; ++i) {
|
||||
outputArray[i] = rawData.charCodeAt(i);
|
||||
}
|
||||
return outputArray;
|
||||
}
|
||||
|
||||
const subscribeToPush = async () => {
|
||||
if (!('serviceWorker' in navigator)) return;
|
||||
|
||||
// 1. 获取 VAPID 公钥
|
||||
const response = await fetch('/api/notification/vapid-public-key');
|
||||
const { publicKey } = await response.json();
|
||||
|
||||
// 2. 等待 Service Worker 准备就绪
|
||||
const registration = await navigator.serviceWorker.ready;
|
||||
|
||||
// 3. 请求订阅
|
||||
const subscription = await registration.pushManager.subscribe({
|
||||
userVisibleOnly: true,
|
||||
applicationServerKey: urlBase64ToUint8Array(publicKey)
|
||||
});
|
||||
|
||||
// 4. 将订阅信息发送给后端
|
||||
// 注意:后端 PushSubscriptionEntity 字段首字母大写,这里需要转换或让后端兼容
|
||||
const subJson = subscription.toJSON();
|
||||
await fetch('/api/notification/subscribe', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
endpoint: subJson.endpoint,
|
||||
p256dh: subJson.keys.p256dh,
|
||||
auth: subJson.keys.auth
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
Reference in New Issue
Block a user