Browse Source

feat(config): add comment email fields in admin global config

Expose comment mail global config fields in the frontend composable and admin config page so admins can view and save notification mail settings.

Made-with: Cursor
main
npmrun 3 weeks ago
parent
commit
28fc538b64
  1. 14
      app/composables/useGlobalConfig.ts
  2. 92
      app/pages/me/admin/config/index.vue

14
app/composables/useGlobalConfig.ts

@ -3,6 +3,13 @@ import { request, unwrapApiBody, type ApiResponse } from '../utils/http/factory'
export type GlobalConfig = { export type GlobalConfig = {
siteName: string siteName: string
allowRegister: boolean allowRegister: boolean
commentEmailNotifyEnabled: boolean
commentMailFromEmail: string
commentSmtpHost: string
commentSmtpPort: number
commentSmtpSecure: boolean
commentSmtpUser: string
commentSmtpPass: string
} }
type GlobalConfigResult = { type GlobalConfigResult = {
@ -12,6 +19,13 @@ type GlobalConfigResult = {
const DEFAULT_GLOBAL_CONFIG: GlobalConfig = { const DEFAULT_GLOBAL_CONFIG: GlobalConfig = {
siteName: 'Person Panel', siteName: 'Person Panel',
allowRegister: true, allowRegister: true,
commentEmailNotifyEnabled: false,
commentMailFromEmail: '',
commentSmtpHost: '',
commentSmtpPort: 465,
commentSmtpSecure: true,
commentSmtpUser: '',
commentSmtpPass: '',
} }
export function useGlobalConfig() { export function useGlobalConfig() {

92
app/pages/me/admin/config/index.vue

@ -9,6 +9,13 @@ type GlobalConfigPayload = {
allowRegister: boolean allowRegister: boolean
mediaOrphanAutoSweepEnabled: boolean mediaOrphanAutoSweepEnabled: boolean
mediaOrphanAutoSweepIntervalMinutes: number mediaOrphanAutoSweepIntervalMinutes: number
commentEmailNotifyEnabled: boolean
commentMailFromEmail: string
commentSmtpHost: string
commentSmtpPort: number
commentSmtpSecure: boolean
commentSmtpUser: string
commentSmtpPass: string
} }
} }
@ -23,6 +30,13 @@ const siteName = ref('')
const allowRegister = ref(true) const allowRegister = ref(true)
const mediaOrphanAutoSweepEnabled = ref(false) const mediaOrphanAutoSweepEnabled = ref(false)
const mediaOrphanAutoSweepIntervalMinutes = ref(60) const mediaOrphanAutoSweepIntervalMinutes = ref(60)
const commentEmailNotifyEnabled = ref(false)
const commentMailFromEmail = ref('')
const commentSmtpHost = ref('')
const commentSmtpPort = ref(465)
const commentSmtpSecure = ref(true)
const commentSmtpUser = ref('')
const commentSmtpPass = ref('')
async function ensureAdmin() { async function ensureAdmin() {
await refresh(true) await refresh(true)
@ -39,6 +53,13 @@ async function load() {
allowRegister.value = cfg.allowRegister allowRegister.value = cfg.allowRegister
mediaOrphanAutoSweepEnabled.value = cfg.mediaOrphanAutoSweepEnabled mediaOrphanAutoSweepEnabled.value = cfg.mediaOrphanAutoSweepEnabled
mediaOrphanAutoSweepIntervalMinutes.value = cfg.mediaOrphanAutoSweepIntervalMinutes mediaOrphanAutoSweepIntervalMinutes.value = cfg.mediaOrphanAutoSweepIntervalMinutes
commentEmailNotifyEnabled.value = cfg.commentEmailNotifyEnabled
commentMailFromEmail.value = cfg.commentMailFromEmail
commentSmtpHost.value = cfg.commentSmtpHost
commentSmtpPort.value = cfg.commentSmtpPort
commentSmtpSecure.value = cfg.commentSmtpSecure
commentSmtpUser.value = cfg.commentSmtpUser
commentSmtpPass.value = cfg.commentSmtpPass
} finally { } finally {
loading.value = false loading.value = false
} }
@ -63,6 +84,13 @@ async function save() {
await putKey('allowRegister', allowRegister.value) await putKey('allowRegister', allowRegister.value)
await putKey('mediaOrphanAutoSweepEnabled', mediaOrphanAutoSweepEnabled.value) await putKey('mediaOrphanAutoSweepEnabled', mediaOrphanAutoSweepEnabled.value)
await putKey('mediaOrphanAutoSweepIntervalMinutes', mediaOrphanAutoSweepIntervalMinutes.value) await putKey('mediaOrphanAutoSweepIntervalMinutes', mediaOrphanAutoSweepIntervalMinutes.value)
await putKey('commentEmailNotifyEnabled', commentEmailNotifyEnabled.value)
await putKey('commentMailFromEmail', commentMailFromEmail.value.trim())
await putKey('commentSmtpHost', commentSmtpHost.value.trim())
await putKey('commentSmtpPort', commentSmtpPort.value)
await putKey('commentSmtpSecure', commentSmtpSecure.value)
await putKey('commentSmtpUser', commentSmtpUser.value.trim())
await putKey('commentSmtpPass', commentSmtpPass.value.trim())
await load() await load()
await refreshGlobalConfig() await refreshGlobalConfig()
toast.add({ title: '配置已保存', color: 'success' }) toast.add({ title: '配置已保存', color: 'success' })
@ -78,7 +106,7 @@ async function save() {
应用配置 应用配置
</h1> </h1>
<p class="text-sm text-muted"> <p class="text-sm text-muted">
全局设置站点名称开放注册与媒体孤儿自动清扫 全局设置站点名称开放注册媒体孤儿自动清扫与评论通知邮件
</p> </p>
<UCard> <UCard>
@ -121,5 +149,67 @@ async function save() {
</UButton> </UButton>
</div> </div>
</UCard> </UCard>
<UCard>
<template #header>
评论通知邮件
</template>
<div v-if="loading" class="text-muted">
加载中
</div>
<div v-else class="space-y-4 max-w-xl">
<UFormField
label="启用评论邮件通知"
description="关闭后将跳过评论邮件发送。"
>
<UCheckbox v-model="commentEmailNotifyEnabled" label="开启通知发送" />
</UFormField>
<UFormField
label="发件人邮箱"
description="用于邮件 From 字段,留空表示未配置。"
>
<UInput v-model="commentMailFromEmail" placeholder="noreply@example.com" />
</UFormField>
<UFormField
label="SMTP 主机"
description="例如 smtp.example.com。"
>
<UInput v-model="commentSmtpHost" placeholder="smtp.example.com" />
</UFormField>
<UFormField
label="SMTP 端口"
description="范围 1-65535,常见 465 或 587。"
>
<UInput
v-model.number="commentSmtpPort"
type="number"
:min="1"
:max="65535"
step="1"
/>
</UFormField>
<UFormField
label="SMTP 安全连接"
description="通常 SSL 对应 465,TLS/STARTTLS 可按服务商要求配置。"
>
<UCheckbox v-model="commentSmtpSecure" label="使用安全连接" />
</UFormField>
<UFormField
label="SMTP 用户名"
description="通常为邮箱地址或服务商提供的账号。"
>
<UInput v-model="commentSmtpUser" placeholder="smtp user" />
</UFormField>
<UFormField
label="SMTP 密码"
description="建议使用邮箱服务商的应用专用密码。"
>
<UInput v-model="commentSmtpPass" type="password" placeholder="smtp password" />
</UFormField>
<UButton :loading="saving" @click="save">
保存
</UButton>
</div>
</UCard>
</UContainer> </UContainer>
</template> </template>

Loading…
Cancel
Save