156 lines
5.7 KiB
Vue
156 lines
5.7 KiB
Vue
<template>
|
||
<div class="aksrt-page-container content-page">
|
||
<PageHeader title="通知管理" desc="管理通知内容开关、user 徽标统计口径和自动清理策略。">
|
||
<template #actions>
|
||
<n-space>
|
||
<n-button :loading="cleaning" @click="runCleanup">立即清理</n-button>
|
||
<n-button type="primary" :loading="saving" @click="saveSettings">保存</n-button>
|
||
</n-space>
|
||
</template>
|
||
</PageHeader>
|
||
|
||
<n-spin :show="loading" style="width: 100%; min-height: 200px;">
|
||
<n-card title="通知内容开关" class="aksrt-section-card">
|
||
<n-form :model="settings" label-placement="left" label-width="180">
|
||
<n-form-item label="评论回复通知">
|
||
<n-switch v-model:value="settings.enabled_types.comment_reply" />
|
||
</n-form-item>
|
||
<n-form-item label="评论审核通过通知">
|
||
<n-switch v-model:value="settings.enabled_types.comment_approved" />
|
||
</n-form-item>
|
||
<n-form-item label="资源下载就绪通知">
|
||
<n-switch v-model:value="settings.enabled_types.download_ready" />
|
||
</n-form-item>
|
||
<n-form-item label="积分增加通知">
|
||
<n-switch v-model:value="settings.enabled_types.credits_added" />
|
||
</n-form-item>
|
||
<n-form-item label="积分扣减通知">
|
||
<n-switch v-model:value="settings.enabled_types.credits_deducted" />
|
||
</n-form-item>
|
||
<n-form-item label="邮箱待验证提醒">
|
||
<n-switch v-model:value="settings.enabled_types.verify_email" />
|
||
</n-form-item>
|
||
<n-form-item label="待审核评论提醒">
|
||
<n-switch v-model:value="settings.enabled_types.pending_comments" />
|
||
</n-form-item>
|
||
<n-form-item label="图片审核通知">
|
||
<n-switch v-model:value="settings.enabled_types.upload_moderation" />
|
||
</n-form-item>
|
||
</n-form>
|
||
</n-card>
|
||
|
||
<n-grid :cols="2" :x-gap="16" responsive="screen" item-responsive style="margin-top: 16px;">
|
||
<n-grid-item span="24 l:10">
|
||
<n-card title="user 徽标规则" class="aksrt-section-card">
|
||
<n-form :model="settings" label-placement="left" label-width="180">
|
||
<n-form-item label="启用 user 动态徽标">
|
||
<n-switch v-model:value="settings.user_badge_enabled" />
|
||
</n-form-item>
|
||
<n-form-item label="徽标包含状态提醒">
|
||
<n-switch v-model:value="settings.badge_include_stateful" />
|
||
<span class="aksrt-hint-text" style="margin-left: 12px;">未读持久化通知之外,叠加邮箱待验证、待审核评论等即时提醒</span>
|
||
</n-form-item>
|
||
</n-form>
|
||
</n-card>
|
||
</n-grid-item>
|
||
|
||
<n-grid-item span="24 l:14">
|
||
<n-card title="通知清理策略" class="aksrt-section-card">
|
||
<n-form :model="settings" label-placement="left" label-width="180">
|
||
<n-form-item label="已读通知保留天数">
|
||
<n-input-number v-model:value="settings.read_retention_days" :min="1" :max="365" style="width: 180px;" />
|
||
</n-form-item>
|
||
<n-form-item label="未读通知保留天数">
|
||
<n-input-number v-model:value="settings.unread_retention_days" :min="7" :max="3650" style="width: 180px;" />
|
||
</n-form-item>
|
||
<n-form-item label="每用户最大保留数">
|
||
<n-input-number v-model:value="settings.max_per_user" :min="20" :max="5000" style="width: 180px;" />
|
||
</n-form-item>
|
||
</n-form>
|
||
</n-card>
|
||
</n-grid-item>
|
||
</n-grid>
|
||
</n-spin>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { onMounted, reactive, ref } from 'vue'
|
||
import { useMessage } from 'naive-ui'
|
||
import api from '@/api'
|
||
import PageHeader from '@/components/PageHeader.vue'
|
||
|
||
const message = useMessage()
|
||
const loading = ref(true)
|
||
const saving = ref(false)
|
||
const cleaning = ref(false)
|
||
|
||
const settings = reactive({
|
||
enabled_types: {
|
||
comment_reply: true,
|
||
comment_approved: true,
|
||
download_ready: true,
|
||
credits_added: true,
|
||
credits_deducted: true,
|
||
verify_email: true,
|
||
pending_comments: true,
|
||
upload_moderation: true,
|
||
},
|
||
user_badge_enabled: true,
|
||
badge_include_stateful: true,
|
||
read_retention_days: 30,
|
||
unread_retention_days: 180,
|
||
max_per_user: 200,
|
||
})
|
||
|
||
async function loadSettings() {
|
||
loading.value = true
|
||
try {
|
||
const res = await api.getNotificationSettings()
|
||
if (res.code === 'success' && res.data) {
|
||
Object.assign(settings, res.data)
|
||
if (res.data.enabled_types) {
|
||
settings.enabled_types = { ...settings.enabled_types, ...res.data.enabled_types }
|
||
}
|
||
}
|
||
} catch (e) {
|
||
message.error(e.message || '加载失败')
|
||
} finally {
|
||
loading.value = false
|
||
}
|
||
}
|
||
|
||
async function saveSettings() {
|
||
saving.value = true
|
||
try {
|
||
const res = await api.saveNotificationSettings({
|
||
enabled_types: settings.enabled_types,
|
||
user_badge_enabled: settings.user_badge_enabled,
|
||
badge_include_stateful: settings.badge_include_stateful,
|
||
read_retention_days: settings.read_retention_days,
|
||
unread_retention_days: settings.unread_retention_days,
|
||
max_per_user: settings.max_per_user,
|
||
})
|
||
if (res.code === 'success') message.success(res.message || '保存成功')
|
||
} catch (e) {
|
||
message.error(e.message || '保存失败')
|
||
} finally {
|
||
saving.value = false
|
||
}
|
||
}
|
||
|
||
async function runCleanup() {
|
||
cleaning.value = true
|
||
try {
|
||
const res = await api.runNotificationCleanup()
|
||
if (res.code === 'success') message.success(res.message || '清理完成')
|
||
} catch (e) {
|
||
message.error(e.message || '清理失败')
|
||
} finally {
|
||
cleaning.value = false
|
||
}
|
||
}
|
||
|
||
onMounted(loadSettings)
|
||
</script>
|