✨ smtp服务
This commit is contained in:
+1
-1
@@ -3,7 +3,7 @@ import { message } from '@/composables/useMessage'
|
||||
|
||||
const request = axios.create({
|
||||
baseURL: import.meta.env.VITE_API_BASE_URL || '/api',
|
||||
timeout: 15000,
|
||||
timeout: 60000,
|
||||
})
|
||||
|
||||
// ---- Token 自动刷新 ----
|
||||
|
||||
@@ -132,3 +132,23 @@ export const systemPriceApi = {
|
||||
update: (data: PriceConfig) =>
|
||||
request.put<any, ApiResponse>('/v1/system/config/price', data),
|
||||
}
|
||||
|
||||
|
||||
// ---- SMTP 配置 ----
|
||||
export interface SmtpConfig {
|
||||
smtpHost: string
|
||||
smtpPort: number
|
||||
smtpUsername: string
|
||||
smtpPassword: string
|
||||
fromEmail: string
|
||||
fromName: string
|
||||
}
|
||||
|
||||
export const systemSmtpApi = {
|
||||
get: () =>
|
||||
request.get<any, ApiResponse<SmtpConfig>>('/v1/system/config/smtp'),
|
||||
update: (data: SmtpConfig) =>
|
||||
request.put<any, ApiResponse>('/v1/system/config/smtp', data),
|
||||
test: (toEmail: string) =>
|
||||
request.post<any, ApiResponse>('/v1/system/config/smtp/test', { toEmail }),
|
||||
}
|
||||
|
||||
@@ -8,7 +8,8 @@ import { Switch } from '@/components/ui/switch'
|
||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
|
||||
import { MdEditor } from 'md-editor-v3'
|
||||
import 'md-editor-v3/lib/style.css'
|
||||
import { systemConfigApi, systemPriceApi, type PriceConfig } from '@/api/system'
|
||||
import { Separator } from '@/components/ui/separator'
|
||||
import { systemConfigApi, systemPriceApi, systemSmtpApi, type PriceConfig, type SmtpConfig } from '@/api/system'
|
||||
|
||||
// ---- 公告 ----
|
||||
const announcementLoading = ref(false)
|
||||
@@ -139,10 +140,73 @@ async function savePriceConfig() {
|
||||
}
|
||||
}
|
||||
|
||||
// ---- SMTP 配置 ----
|
||||
const smtpLoading = ref(false)
|
||||
const smtpSaving = ref(false)
|
||||
const smtpTesting = ref(false)
|
||||
const testEmail = ref('')
|
||||
const smtpConfig = ref<SmtpConfig>({
|
||||
smtpHost: '',
|
||||
smtpPort: 587,
|
||||
smtpUsername: '',
|
||||
smtpPassword: '',
|
||||
fromEmail: '',
|
||||
fromName: '',
|
||||
})
|
||||
|
||||
async function fetchSmtpConfig() {
|
||||
smtpLoading.value = true
|
||||
try {
|
||||
const res = await systemSmtpApi.get()
|
||||
if (res.data) {
|
||||
smtpConfig.value = { ...smtpConfig.value, ...res.data }
|
||||
// port 可能是字符串
|
||||
smtpConfig.value.smtpPort = Number(smtpConfig.value.smtpPort) || 587
|
||||
}
|
||||
} catch {
|
||||
// 使用默认值
|
||||
} finally {
|
||||
smtpLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
async function saveSmtpConfig() {
|
||||
if (!smtpConfig.value.smtpHost || !smtpConfig.value.smtpUsername) {
|
||||
toast.error('请填写完整的SMTP配置')
|
||||
return
|
||||
}
|
||||
smtpSaving.value = true
|
||||
try {
|
||||
await systemSmtpApi.update(smtpConfig.value)
|
||||
toast.success('SMTP配置保存成功')
|
||||
} catch {
|
||||
// 全局拦截器已处理
|
||||
} finally {
|
||||
smtpSaving.value = false
|
||||
}
|
||||
}
|
||||
|
||||
async function testSmtp() {
|
||||
if (!testEmail.value.trim()) {
|
||||
toast.error('请输入测试收件邮箱')
|
||||
return
|
||||
}
|
||||
smtpTesting.value = true
|
||||
try {
|
||||
await systemSmtpApi.test(testEmail.value.trim())
|
||||
toast.success('测试邮件发送成功')
|
||||
} catch {
|
||||
// 全局拦截器已处理
|
||||
} finally {
|
||||
smtpTesting.value = false
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
fetchAnnouncement()
|
||||
fetchRegisterConfig()
|
||||
fetchPriceConfig()
|
||||
fetchSmtpConfig()
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -246,5 +310,58 @@ onMounted(() => {
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
<!-- SMTP 邮件配置 -->
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle class="text-base">SMTP 邮件配置</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent class="space-y-4">
|
||||
<div v-if="smtpLoading" class="text-sm text-muted-foreground py-4 text-center">加载中...</div>
|
||||
<template v-else>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 max-w-2xl">
|
||||
<div class="space-y-2">
|
||||
<Label>SMTP 服务器</Label>
|
||||
<Input v-model="smtpConfig.smtpHost" placeholder="如:smtp.qq.com" />
|
||||
</div>
|
||||
<div class="space-y-2">
|
||||
<Label>SMTP 端口</Label>
|
||||
<Input v-model.number="smtpConfig.smtpPort" type="number" placeholder="如:587" />
|
||||
</div>
|
||||
<div class="space-y-2">
|
||||
<Label>SMTP 用户名</Label>
|
||||
<Input v-model="smtpConfig.smtpUsername" placeholder="SMTP登录用户名" />
|
||||
</div>
|
||||
<div class="space-y-2">
|
||||
<Label>SMTP 密码</Label>
|
||||
<Input v-model="smtpConfig.smtpPassword" type="password" placeholder="SMTP登录密码/授权码" />
|
||||
</div>
|
||||
<div class="space-y-2">
|
||||
<Label>发件人邮箱</Label>
|
||||
<Input v-model="smtpConfig.fromEmail" placeholder="发件人邮箱地址" />
|
||||
</div>
|
||||
<div class="space-y-2">
|
||||
<Label>发件人名称</Label>
|
||||
<Input v-model="smtpConfig.fromName" placeholder="发件人显示名称" />
|
||||
</div>
|
||||
</div>
|
||||
<Separator />
|
||||
<div class="flex items-end gap-3 max-w-2xl">
|
||||
<div class="flex-1 space-y-2">
|
||||
<Label>测试收件邮箱</Label>
|
||||
<Input v-model="testEmail" placeholder="输入邮箱地址发送测试邮件" />
|
||||
</div>
|
||||
<Button variant="outline" size="sm" :disabled="smtpTesting" @click="testSmtp">
|
||||
{{ smtpTesting ? '发送中...' : '发送测试' }}
|
||||
</Button>
|
||||
</div>
|
||||
<div class="flex justify-end max-w-2xl">
|
||||
<Button size="sm" :disabled="smtpSaving" @click="saveSmtpConfig">
|
||||
{{ smtpSaving ? '保存中...' : '保存配置' }}
|
||||
</Button>
|
||||
</div>
|
||||
</template>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user