feat: 添加原生通知监听功能,自动同步通知和交易列表

This commit is contained in:
2025-11-28 10:55:03 +08:00
parent cc2c376e9d
commit a2c5525a2e
8 changed files with 1271 additions and 15 deletions

View File

@@ -20,6 +20,7 @@ const ruleSet = ref([])
const nativeBridgeReady = isNativeNotificationBridgeAvailable()
let permissionChecked = false
let bootstrapped = false
let nativeNotificationListener = null
const ensureRulesReady = async () => {
if (ruleSet.value.length) return ruleSet.value
@@ -119,6 +120,19 @@ export const useTransactionEntry = () => {
if (!bootstrapped) {
bootstrapped = true
syncNotifications()
// 原生环境:监听 NotificationBridgePlugin 推送的 notificationPosted 事件,做到“通知一到就同步一次”
if (nativeBridgeReady && !nativeNotificationListener && typeof NotificationBridge?.addListener === 'function') {
NotificationBridge.addListener('notificationPosted', async () => {
await syncNotifications()
})
.then((handle) => {
nativeNotificationListener = handle
})
.catch((error) => {
console.warn('[notifications] 无法注册 notificationPosted 监听', error)
})
}
}
return {

View File

@@ -1,15 +1,39 @@
<script setup>
import { computed } from 'vue'
import { computed, onMounted, onBeforeUnmount } from 'vue'
import { storeToRefs } from 'pinia'
import { App } from '@capacitor/app'
import { useTransactionStore } from '../stores/transactions'
import { useTransactionEntry } from '../composables/useTransactionEntry'
const transactionStore = useTransactionStore()
const { totalIncome, totalExpense, todaysIncome, todaysExpense, latestTransactions } =
storeToRefs(transactionStore)
const { notifications, confirmNotification, dismissNotification, processingId } =
const { notifications, confirmNotification, dismissNotification, processingId, syncNotifications } =
useTransactionEntry()
let appStateListener = null
onMounted(async () => {
try {
// App 从后台回到前台时,自动同步一次通知和交易列表
appStateListener = await App.addListener('appStateChange', async ({ isActive }) => {
if (isActive) {
await syncNotifications()
}
})
} catch (error) {
// Web 环境或插件不可用时忽略
console.warn('[notifications] appStateChange listener failed', error)
}
})
onBeforeUnmount(() => {
if (appStateListener && typeof appStateListener.remove === 'function') {
appStateListener.remove()
}
appStateListener = null
})
const emit = defineEmits(['changeTab'])
const monthlyBudget = 12000