通知系统-1

This commit is contained in:
yml2213
2026-05-14 17:29:12 +08:00
parent 91d74b3e59
commit b6c493d5e7
22 changed files with 1314 additions and 11 deletions
@@ -1,4 +1,4 @@
export type PlatformTab = 'agiso' | 'ninetyone' | 'kuaishouEticket' | 'cloudtentacles'
export type PlatformTab = 'agiso' | 'notifications' | 'ninetyone' | 'kuaishouEticket' | 'cloudtentacles'
export type EditableDefaults = {
messageTemplate: string
@@ -23,3 +23,10 @@ export type EditableKuaishouEticketShop = {
userAvatar: string
enabled: boolean
}
export type EditableNotificationRecipient = {
id: string
name: string
deviceKey: string
enabled: boolean
}
@@ -0,0 +1,152 @@
import { computed, ref } from 'vue'
import { showError, showSuccess } from '@/lib/feedback'
import {
saveAdminNotificationConfig,
testAdminNotification,
} from '@/services/admin'
import type {
AdminNotificationConfig,
AdminNotificationTestResult,
} from '@/types/admin'
import type { EditableNotificationRecipient } from './types'
export function useAdminNotificationPlatform() {
const notificationFilePath = ref('')
const notificationForm = ref({
enabled: true,
barkEnabled: true,
barkServerUrl: 'https://api.day.app',
testTitle: '订单系统测试通知',
testBody: '这是一条 Bark 内部通知测试。',
testUrl: '',
})
const notificationRecipients = ref<EditableNotificationRecipient[]>([])
const notificationSaving = ref(false)
const notificationTesting = ref(false)
const notificationResultError = ref('')
const notificationTestResult = ref<AdminNotificationTestResult | null>(null)
const notificationStats = computed(() => {
const enabledRecipients = notificationRecipients.value.filter((item) => item.enabled && item.deviceKey.trim())
return {
configuredRecipientCount: notificationRecipients.value.length,
enabledRecipientCount: enabledRecipients.length,
barkReady: notificationForm.value.enabled && notificationForm.value.barkEnabled && enabledRecipients.length > 0,
lastSuccessCount: notificationTestResult.value?.successCount || 0,
lastFailedCount: notificationTestResult.value?.failedCount || 0,
}
})
function hydrateNotificationConfig(data: {
filePath: string
source: AdminNotificationConfig
}) {
notificationFilePath.value = data.filePath
notificationForm.value.enabled = data.source.enabled !== false
notificationForm.value.barkEnabled = data.source.channels.bark.enabled !== false
notificationForm.value.barkServerUrl = data.source.channels.bark.serverUrl || 'https://api.day.app'
notificationRecipients.value = data.source.channels.bark.recipients.map((item) => ({
id: item.id || crypto.randomUUID(),
name: item.name,
deviceKey: item.deviceKey,
enabled: item.enabled !== false,
}))
}
function addNotificationRecipient() {
notificationRecipients.value.unshift({
id: crypto.randomUUID(),
name: '',
deviceKey: '',
enabled: true,
})
}
function removeNotificationRecipient(id: string) {
notificationRecipients.value = notificationRecipients.value.filter((item) => item.id !== id)
}
function buildNotificationConfigPayload(): AdminNotificationConfig {
return {
enabled: notificationForm.value.enabled,
channels: {
bark: {
enabled: notificationForm.value.barkEnabled,
serverUrl: notificationForm.value.barkServerUrl.trim() || 'https://api.day.app',
recipients: notificationRecipients.value.map((item) => ({
id: item.id,
name: item.name.trim(),
deviceKey: item.deviceKey.trim(),
deviceKeyMasked: '',
enabled: item.enabled,
})),
},
},
}
}
async function handleNotificationSaveConfig() {
notificationSaving.value = true
notificationResultError.value = ''
try {
const response = await saveAdminNotificationConfig(buildNotificationConfigPayload())
notificationFilePath.value = response.data.filePath
hydrateNotificationConfig(response.data)
showSuccess('内部通知配置已保存')
} catch (error) {
notificationResultError.value = error instanceof Error ? error.message : '内部通知配置保存失败'
showError(notificationResultError.value)
} finally {
notificationSaving.value = false
}
}
async function handleNotificationTest() {
notificationTesting.value = true
notificationResultError.value = ''
notificationTestResult.value = null
try {
const saved = await saveAdminNotificationConfig(buildNotificationConfigPayload())
notificationFilePath.value = saved.data.filePath
hydrateNotificationConfig(saved.data)
const response = await testAdminNotification({
title: notificationForm.value.testTitle.trim(),
body: notificationForm.value.testBody.trim(),
url: notificationForm.value.testUrl.trim(),
})
notificationTestResult.value = response.data
if (response.data.successCount > 0) {
showSuccess(`内部通知测试完成,成功 ${response.data.successCount}`)
} else {
showError('内部通知测试未成功发送,请检查 Bark 配置')
}
} catch (error) {
notificationResultError.value = error instanceof Error ? error.message : '内部通知测试失败'
showError(notificationResultError.value)
} finally {
notificationTesting.value = false
}
}
return {
notificationFilePath,
notificationForm,
notificationRecipients,
notificationSaving,
notificationTesting,
notificationResultError,
notificationTestResult,
notificationStats,
hydrateNotificationConfig,
addNotificationRecipient,
removeNotificationRecipient,
handleNotificationSaveConfig,
handleNotificationTest,
}
}