- 添加基于 VbenAdmin + Vue3 + Element Plus 的前端管理系统 - 包含完整的 UI 组件库和工具链 - 支持多应用架构 (web-ele, backend-mock, playground) - 包含完整的开发规范和配置 - 修复 admin 目录的子模块问题,确保正确提交
905 lines
29 KiB
Vue
905 lines
29 KiB
Vue
<template>
|
||
<Page>
|
||
<el-card>
|
||
<template #header>
|
||
<div class="card-header">
|
||
<Icon icon="ep:bell" class="mr-2" />
|
||
<span>通知设置</span>
|
||
</div>
|
||
</template>
|
||
|
||
<el-tabs v-model="activeTab" type="border-card">
|
||
<!-- 邮件通知 -->
|
||
<el-tab-pane label="邮件通知" name="email">
|
||
<el-form
|
||
ref="emailFormRef"
|
||
:model="emailForm"
|
||
:rules="emailRules"
|
||
label-width="150px"
|
||
v-loading="loading"
|
||
>
|
||
<el-form-item label="启用邮件通知" prop="enabled">
|
||
<el-switch
|
||
v-model="emailForm.enabled"
|
||
active-text="启用"
|
||
inactive-text="禁用"
|
||
/>
|
||
<div class="form-item-tip">启用后系统将发送邮件通知</div>
|
||
</el-form-item>
|
||
|
||
<template v-if="emailForm.enabled">
|
||
<el-form-item label="通知类型" prop="types">
|
||
<el-checkbox-group v-model="emailForm.types">
|
||
<el-checkbox label="user_register">用户注册</el-checkbox>
|
||
<el-checkbox label="user_login">用户登录</el-checkbox>
|
||
<el-checkbox label="password_reset">密码重置</el-checkbox>
|
||
<el-checkbox label="order_created">订单创建</el-checkbox>
|
||
<el-checkbox label="order_paid">订单支付</el-checkbox>
|
||
<el-checkbox label="order_shipped">订单发货</el-checkbox>
|
||
<el-checkbox label="order_completed">订单完成</el-checkbox>
|
||
<el-checkbox label="system_error">系统错误</el-checkbox>
|
||
<el-checkbox label="security_alert">安全警报</el-checkbox>
|
||
</el-checkbox-group>
|
||
</el-form-item>
|
||
|
||
<el-form-item label="管理员邮箱" prop="adminEmails">
|
||
<div class="email-list-container">
|
||
<div class="email-list">
|
||
<div v-for="(email, index) in emailForm.adminEmails" :key="index" class="email-item">
|
||
<el-input
|
||
v-model="emailForm.adminEmails[index]"
|
||
placeholder="请输入管理员邮箱"
|
||
clearable
|
||
/>
|
||
<el-button
|
||
type="danger"
|
||
text
|
||
@click="removeAdminEmail(index)"
|
||
class="ml-2"
|
||
>
|
||
<Icon icon="ep:delete" />
|
||
</el-button>
|
||
</div>
|
||
</div>
|
||
<el-button @click="addAdminEmail" type="primary" text class="mt-2">
|
||
<Icon icon="ep:plus" class="mr-1" />
|
||
添加邮箱
|
||
</el-button>
|
||
</div>
|
||
</el-form-item>
|
||
|
||
<el-form-item label="发送频率限制" prop="rateLimit">
|
||
<el-input-number
|
||
v-model="emailForm.rateLimit"
|
||
:min="1"
|
||
:max="100"
|
||
style="width: 200px"
|
||
/>
|
||
<span class="ml-2">封/小时</span>
|
||
<div class="form-item-tip">限制每小时发送的邮件数量</div>
|
||
</el-form-item>
|
||
|
||
<el-form-item label="重试次数" prop="retryTimes">
|
||
<el-input-number
|
||
v-model="emailForm.retryTimes"
|
||
:min="0"
|
||
:max="5"
|
||
style="width: 200px"
|
||
/>
|
||
<span class="ml-2">次</span>
|
||
</el-form-item>
|
||
|
||
<el-form-item label="队列延迟" prop="queueDelay">
|
||
<el-input-number
|
||
v-model="emailForm.queueDelay"
|
||
:min="0"
|
||
:max="3600"
|
||
style="width: 200px"
|
||
/>
|
||
<span class="ml-2">秒</span>
|
||
<div class="form-item-tip">邮件发送延迟时间</div>
|
||
</el-form-item>
|
||
</template>
|
||
|
||
<el-form-item>
|
||
<el-button type="primary" @click="handleSaveEmail" :loading="saveLoading">
|
||
<Icon icon="ep:check" class="mr-1" />
|
||
保存设置
|
||
</el-button>
|
||
<el-button @click="handleResetEmail">
|
||
<Icon icon="ep:refresh" class="mr-1" />
|
||
重置
|
||
</el-button>
|
||
<el-button @click="handleTestEmail" :loading="testEmailLoading" v-if="emailForm.enabled">
|
||
<Icon icon="ep:message" class="mr-1" />
|
||
发送测试邮件
|
||
</el-button>
|
||
</el-form-item>
|
||
</el-form>
|
||
</el-tab-pane>
|
||
|
||
<!-- 短信通知 -->
|
||
<el-tab-pane label="短信通知" name="sms">
|
||
<el-form
|
||
ref="smsFormRef"
|
||
:model="smsForm"
|
||
:rules="smsRules"
|
||
label-width="150px"
|
||
v-loading="loading"
|
||
>
|
||
<el-form-item label="启用短信通知" prop="enabled">
|
||
<el-switch
|
||
v-model="smsForm.enabled"
|
||
active-text="启用"
|
||
inactive-text="禁用"
|
||
/>
|
||
<div class="form-item-tip">启用后系统将发送短信通知</div>
|
||
</el-form-item>
|
||
|
||
<template v-if="smsForm.enabled">
|
||
<el-form-item label="通知类型" prop="types">
|
||
<el-checkbox-group v-model="smsForm.types">
|
||
<el-checkbox label="user_register">用户注册</el-checkbox>
|
||
<el-checkbox label="login_verify">登录验证</el-checkbox>
|
||
<el-checkbox label="password_reset">密码重置</el-checkbox>
|
||
<el-checkbox label="order_status">订单状态变更</el-checkbox>
|
||
<el-checkbox label="payment_notify">支付通知</el-checkbox>
|
||
<el-checkbox label="security_alert">安全警报</el-checkbox>
|
||
<el-checkbox label="marketing">营销推广</el-checkbox>
|
||
</el-checkbox-group>
|
||
</el-form-item>
|
||
|
||
<el-form-item label="管理员手机" prop="adminPhones">
|
||
<div class="phone-list-container">
|
||
<div class="phone-list">
|
||
<div v-for="(phone, index) in smsForm.adminPhones" :key="index" class="phone-item">
|
||
<el-input
|
||
v-model="smsForm.adminPhones[index]"
|
||
placeholder="请输入管理员手机号"
|
||
clearable
|
||
/>
|
||
<el-button
|
||
type="danger"
|
||
text
|
||
@click="removeAdminPhone(index)"
|
||
class="ml-2"
|
||
>
|
||
<Icon icon="ep:delete" />
|
||
</el-button>
|
||
</div>
|
||
</div>
|
||
<el-button @click="addAdminPhone" type="primary" text class="mt-2">
|
||
<Icon icon="ep:plus" class="mr-1" />
|
||
添加手机号
|
||
</el-button>
|
||
</div>
|
||
</el-form-item>
|
||
|
||
<el-form-item label="发送时间限制">
|
||
<el-row :gutter="20">
|
||
<el-col :span="12">
|
||
<el-form-item label="开始时间" prop="sendTimeStart" label-width="80px">
|
||
<el-time-picker
|
||
v-model="smsForm.sendTimeStart"
|
||
format="HH:mm"
|
||
value-format="HH:mm"
|
||
placeholder="选择开始时间"
|
||
/>
|
||
</el-form-item>
|
||
</el-col>
|
||
<el-col :span="12">
|
||
<el-form-item label="结束时间" prop="sendTimeEnd" label-width="80px">
|
||
<el-time-picker
|
||
v-model="smsForm.sendTimeEnd"
|
||
format="HH:mm"
|
||
value-format="HH:mm"
|
||
placeholder="选择结束时间"
|
||
/>
|
||
</el-form-item>
|
||
</el-col>
|
||
</el-row>
|
||
<div class="form-item-tip">限制短信发送的时间段,避免打扰用户</div>
|
||
</el-form-item>
|
||
|
||
<el-form-item label="发送频率限制" prop="rateLimit">
|
||
<el-input-number
|
||
v-model="smsForm.rateLimit"
|
||
:min="1"
|
||
:max="1000"
|
||
style="width: 200px"
|
||
/>
|
||
<span class="ml-2">条/小时</span>
|
||
</el-form-item>
|
||
|
||
<el-form-item label="同号码限制" prop="phoneLimit">
|
||
<el-input-number
|
||
v-model="smsForm.phoneLimit"
|
||
:min="1"
|
||
:max="10"
|
||
style="width: 200px"
|
||
/>
|
||
<span class="ml-2">条/天</span>
|
||
<div class="form-item-tip">限制同一手机号每天接收的短信数量</div>
|
||
</el-form-item>
|
||
</template>
|
||
|
||
<el-form-item>
|
||
<el-button type="primary" @click="handleSaveSms" :loading="saveLoading">
|
||
<Icon icon="ep:check" class="mr-1" />
|
||
保存设置
|
||
</el-button>
|
||
<el-button @click="handleResetSms">
|
||
<Icon icon="ep:refresh" class="mr-1" />
|
||
重置
|
||
</el-button>
|
||
<el-button @click="handleTestSms" :loading="testSmsLoading" v-if="smsForm.enabled">
|
||
<Icon icon="ep:chat-dot-round" class="mr-1" />
|
||
发送测试短信
|
||
</el-button>
|
||
</el-form-item>
|
||
</el-form>
|
||
</el-tab-pane>
|
||
|
||
<!-- 站内通知 -->
|
||
<el-tab-pane label="站内通知" name="system">
|
||
<el-form
|
||
ref="systemFormRef"
|
||
:model="systemForm"
|
||
:rules="systemRules"
|
||
label-width="150px"
|
||
v-loading="loading"
|
||
>
|
||
<el-form-item label="启用站内通知" prop="enabled">
|
||
<el-switch
|
||
v-model="systemForm.enabled"
|
||
active-text="启用"
|
||
inactive-text="禁用"
|
||
/>
|
||
<div class="form-item-tip">启用后系统将发送站内消息通知</div>
|
||
</el-form-item>
|
||
|
||
<template v-if="systemForm.enabled">
|
||
<el-form-item label="通知类型" prop="types">
|
||
<el-checkbox-group v-model="systemForm.types">
|
||
<el-checkbox label="user_register">用户注册</el-checkbox>
|
||
<el-checkbox label="order_created">订单创建</el-checkbox>
|
||
<el-checkbox label="order_paid">订单支付</el-checkbox>
|
||
<el-checkbox label="order_shipped">订单发货</el-checkbox>
|
||
<el-checkbox label="order_completed">订单完成</el-checkbox>
|
||
<el-checkbox label="order_refund">订单退款</el-checkbox>
|
||
<el-checkbox label="user_feedback">用户反馈</el-checkbox>
|
||
<el-checkbox label="system_maintenance">系统维护</el-checkbox>
|
||
<el-checkbox label="promotion">促销活动</el-checkbox>
|
||
</el-checkbox-group>
|
||
</el-form-item>
|
||
|
||
<el-form-item label="消息保留期" prop="retentionDays">
|
||
<el-input-number
|
||
v-model="systemForm.retentionDays"
|
||
:min="7"
|
||
:max="365"
|
||
style="width: 200px"
|
||
/>
|
||
<span class="ml-2">天</span>
|
||
<div class="form-item-tip">超过保留期的消息将被自动删除</div>
|
||
</el-form-item>
|
||
|
||
<el-form-item label="最大消息数" prop="maxMessages">
|
||
<el-input-number
|
||
v-model="systemForm.maxMessages"
|
||
:min="100"
|
||
:max="10000"
|
||
style="width: 200px"
|
||
/>
|
||
<span class="ml-2">条</span>
|
||
<div class="form-item-tip">每个用户最多保留的消息数量</div>
|
||
</el-form-item>
|
||
|
||
<el-form-item label="自动标记已读" prop="autoMarkRead">
|
||
<el-switch
|
||
v-model="systemForm.autoMarkRead"
|
||
active-text="启用"
|
||
inactive-text="禁用"
|
||
/>
|
||
<div class="form-item-tip">用户查看消息后自动标记为已读</div>
|
||
</el-form-item>
|
||
|
||
<el-form-item label="推送到桌面" prop="desktopPush">
|
||
<el-switch
|
||
v-model="systemForm.desktopPush"
|
||
active-text="启用"
|
||
inactive-text="禁用"
|
||
/>
|
||
<div class="form-item-tip">支持浏览器桌面通知推送</div>
|
||
</el-form-item>
|
||
|
||
<el-form-item label="声音提醒" prop="soundAlert">
|
||
<el-switch
|
||
v-model="systemForm.soundAlert"
|
||
active-text="启用"
|
||
inactive-text="禁用"
|
||
/>
|
||
<div class="form-item-tip">新消息时播放提示音</div>
|
||
</el-form-item>
|
||
</template>
|
||
|
||
<el-form-item>
|
||
<el-button type="primary" @click="handleSaveSystem" :loading="saveLoading">
|
||
<Icon icon="ep:check" class="mr-1" />
|
||
保存设置
|
||
</el-button>
|
||
<el-button @click="handleResetSystem">
|
||
<Icon icon="ep:refresh" class="mr-1" />
|
||
重置
|
||
</el-button>
|
||
<el-button @click="handleTestSystem" :loading="testSystemLoading" v-if="systemForm.enabled">
|
||
<Icon icon="ep:bell" class="mr-1" />
|
||
发送测试通知
|
||
</el-button>
|
||
</el-form-item>
|
||
</el-form>
|
||
</el-tab-pane>
|
||
|
||
<!-- 微信通知 -->
|
||
<el-tab-pane label="微信通知" name="wechat">
|
||
<el-form
|
||
ref="wechatFormRef"
|
||
:model="wechatForm"
|
||
:rules="wechatRules"
|
||
label-width="150px"
|
||
v-loading="loading"
|
||
>
|
||
<el-form-item label="启用微信通知" prop="enabled">
|
||
<el-switch
|
||
v-model="wechatForm.enabled"
|
||
active-text="启用"
|
||
inactive-text="禁用"
|
||
/>
|
||
<div class="form-item-tip">启用后系统将发送微信模板消息</div>
|
||
</el-form-item>
|
||
|
||
<template v-if="wechatForm.enabled">
|
||
<el-form-item label="AppID" prop="appId">
|
||
<el-input
|
||
v-model="wechatForm.appId"
|
||
placeholder="请输入微信公众号AppID"
|
||
clearable
|
||
/>
|
||
</el-form-item>
|
||
|
||
<el-form-item label="AppSecret" prop="appSecret">
|
||
<el-input
|
||
v-model="wechatForm.appSecret"
|
||
type="password"
|
||
placeholder="请输入微信公众号AppSecret"
|
||
show-password
|
||
clearable
|
||
/>
|
||
</el-form-item>
|
||
|
||
<el-form-item label="通知类型" prop="types">
|
||
<el-checkbox-group v-model="wechatForm.types">
|
||
<el-checkbox label="order_created">订单创建</el-checkbox>
|
||
<el-checkbox label="order_paid">订单支付</el-checkbox>
|
||
<el-checkbox label="order_shipped">订单发货</el-checkbox>
|
||
<el-checkbox label="order_completed">订单完成</el-checkbox>
|
||
<el-checkbox label="order_refund">订单退款</el-checkbox>
|
||
<el-checkbox label="payment_success">支付成功</el-checkbox>
|
||
<el-checkbox label="account_change">账户变动</el-checkbox>
|
||
<el-checkbox label="service_notice">服务通知</el-checkbox>
|
||
</el-checkbox-group>
|
||
</el-form-item>
|
||
|
||
<el-form-item label="模板消息配置">
|
||
<div class="template-config">
|
||
<div v-for="(template, key) in wechatForm.templates" :key="key" class="template-item">
|
||
<div class="template-label">{{ getTemplateLabel(key) }}</div>
|
||
<el-input
|
||
v-model="wechatForm.templates[key]"
|
||
placeholder="请输入模板ID"
|
||
clearable
|
||
/>
|
||
</div>
|
||
</div>
|
||
</el-form-item>
|
||
|
||
<el-form-item label="发送频率限制" prop="rateLimit">
|
||
<el-input-number
|
||
v-model="wechatForm.rateLimit"
|
||
:min="1"
|
||
:max="1000"
|
||
style="width: 200px"
|
||
/>
|
||
<span class="ml-2">条/小时</span>
|
||
</el-form-item>
|
||
</template>
|
||
|
||
<el-form-item>
|
||
<el-button type="primary" @click="handleSaveWechat" :loading="saveLoading">
|
||
<Icon icon="ep:check" class="mr-1" />
|
||
保存设置
|
||
</el-button>
|
||
<el-button @click="handleResetWechat">
|
||
<Icon icon="ep:refresh" class="mr-1" />
|
||
重置
|
||
</el-button>
|
||
<el-button @click="handleTestWechat" :loading="testWechatLoading" v-if="wechatForm.enabled">
|
||
<Icon icon="ep:chat-dot-round" class="mr-1" />
|
||
发送测试消息
|
||
</el-button>
|
||
</el-form-item>
|
||
</el-form>
|
||
</el-tab-pane>
|
||
</el-tabs>
|
||
</el-card>
|
||
</Page>
|
||
</template>
|
||
|
||
<script lang="ts" setup>
|
||
// 1. Vue 相关导入
|
||
import { ref, reactive, onMounted } from 'vue';
|
||
import type { FormInstance } from 'element-plus';
|
||
|
||
// 2. Element Plus 组件导入
|
||
import {
|
||
ElButton,
|
||
ElCard,
|
||
ElCheckbox,
|
||
ElCheckboxGroup,
|
||
ElCol,
|
||
ElForm,
|
||
ElFormItem,
|
||
ElInput,
|
||
ElInputNumber,
|
||
ElMessage,
|
||
ElRow,
|
||
ElSwitch,
|
||
ElTabPane,
|
||
ElTabs,
|
||
ElTimePicker,
|
||
} from 'element-plus';
|
||
|
||
// 3. 图标组件导入
|
||
import { Icon } from '@iconify/vue';
|
||
|
||
// 4. Vben 组件导入
|
||
import { Page } from '@vben/common-ui';
|
||
|
||
// 5. 项目内部导入
|
||
import {
|
||
getNotificationSettingsApi,
|
||
updateNotificationSettingsApi,
|
||
resetNotificationSettingsApi,
|
||
testNotificationApi,
|
||
type NotificationSettings,
|
||
type UpdateNotificationSettingsParams,
|
||
} from '#/api/settings';
|
||
|
||
// 响应式数据
|
||
const loading = ref(false);
|
||
const saveLoading = ref(false);
|
||
const testEmailLoading = ref(false);
|
||
const testSmsLoading = ref(false);
|
||
const testSystemLoading = ref(false);
|
||
const testWechatLoading = ref(false);
|
||
const activeTab = ref('email');
|
||
const emailFormRef = ref<FormInstance>();
|
||
const smsFormRef = ref<FormInstance>();
|
||
const systemFormRef = ref<FormInstance>();
|
||
const wechatFormRef = ref<FormInstance>();
|
||
|
||
// 邮件通知表单
|
||
const emailForm = reactive({
|
||
enabled: true,
|
||
types: ['user_register', 'order_created', 'system_error'],
|
||
adminEmails: ['admin@example.com'],
|
||
rateLimit: 50,
|
||
retryTimes: 3,
|
||
queueDelay: 0,
|
||
});
|
||
|
||
// 短信通知表单
|
||
const smsForm = reactive({
|
||
enabled: false,
|
||
types: ['user_register', 'login_verify', 'password_reset'],
|
||
adminPhones: [''],
|
||
sendTimeStart: '08:00',
|
||
sendTimeEnd: '22:00',
|
||
rateLimit: 100,
|
||
phoneLimit: 5,
|
||
});
|
||
|
||
// 站内通知表单
|
||
const systemForm = reactive({
|
||
enabled: true,
|
||
types: ['user_register', 'order_created', 'order_paid'],
|
||
retentionDays: 30,
|
||
maxMessages: 1000,
|
||
autoMarkRead: true,
|
||
desktopPush: false,
|
||
soundAlert: true,
|
||
});
|
||
|
||
// 微信通知表单
|
||
const wechatForm = reactive({
|
||
enabled: false,
|
||
appId: '',
|
||
appSecret: '',
|
||
types: ['order_created', 'order_paid', 'payment_success'],
|
||
templates: {
|
||
order_created: '',
|
||
order_paid: '',
|
||
order_shipped: '',
|
||
order_completed: '',
|
||
order_refund: '',
|
||
payment_success: '',
|
||
account_change: '',
|
||
service_notice: '',
|
||
},
|
||
rateLimit: 100,
|
||
});
|
||
|
||
// 表单验证规则
|
||
const emailRules = {
|
||
adminEmails: [
|
||
{ required: true, message: '请输入管理员邮箱', trigger: 'blur' },
|
||
],
|
||
rateLimit: [
|
||
{ required: true, message: '请输入发送频率限制', trigger: 'blur' },
|
||
{ type: 'number', min: 1, max: 100, message: '发送频率范围为 1-100 封/小时', trigger: 'blur' },
|
||
],
|
||
};
|
||
|
||
const smsRules = {
|
||
adminPhones: [
|
||
{ required: true, message: '请输入管理员手机号', trigger: 'blur' },
|
||
],
|
||
rateLimit: [
|
||
{ required: true, message: '请输入发送频率限制', trigger: 'blur' },
|
||
{ type: 'number', min: 1, max: 1000, message: '发送频率范围为 1-1000 条/小时', trigger: 'blur' },
|
||
],
|
||
};
|
||
|
||
const systemRules = {
|
||
retentionDays: [
|
||
{ required: true, message: '请输入消息保留期', trigger: 'blur' },
|
||
{ type: 'number', min: 7, max: 365, message: '保留期范围为 7-365 天', trigger: 'blur' },
|
||
],
|
||
maxMessages: [
|
||
{ required: true, message: '请输入最大消息数', trigger: 'blur' },
|
||
{ type: 'number', min: 100, max: 10000, message: '消息数范围为 100-10000 条', trigger: 'blur' },
|
||
],
|
||
};
|
||
|
||
const wechatRules = {
|
||
appId: [
|
||
{ required: true, message: '请输入微信AppID', trigger: 'blur' },
|
||
],
|
||
appSecret: [
|
||
{ required: true, message: '请输入微信AppSecret', trigger: 'blur' },
|
||
],
|
||
};
|
||
|
||
// 方法
|
||
const addAdminEmail = () => {
|
||
emailForm.adminEmails.push('');
|
||
};
|
||
|
||
const removeAdminEmail = (index: number) => {
|
||
if (emailForm.adminEmails.length > 1) {
|
||
emailForm.adminEmails.splice(index, 1);
|
||
}
|
||
};
|
||
|
||
const addAdminPhone = () => {
|
||
smsForm.adminPhones.push('');
|
||
};
|
||
|
||
const removeAdminPhone = (index: number) => {
|
||
if (smsForm.adminPhones.length > 1) {
|
||
smsForm.adminPhones.splice(index, 1);
|
||
}
|
||
};
|
||
|
||
const getTemplateLabel = (key: string) => {
|
||
const labels: Record<string, string> = {
|
||
order_created: '订单创建',
|
||
order_paid: '订单支付',
|
||
order_shipped: '订单发货',
|
||
order_completed: '订单完成',
|
||
order_refund: '订单退款',
|
||
payment_success: '支付成功',
|
||
account_change: '账户变动',
|
||
service_notice: '服务通知',
|
||
};
|
||
return labels[key] || key;
|
||
};
|
||
|
||
const loadSettings = async () => {
|
||
loading.value = true;
|
||
try {
|
||
const settings = await getNotificationSettingsApi();
|
||
Object.assign(emailForm, settings.email || {});
|
||
Object.assign(smsForm, settings.sms || {});
|
||
Object.assign(systemForm, settings.system || {});
|
||
Object.assign(wechatForm, settings.wechat || {});
|
||
} catch (error) {
|
||
ElMessage.error('加载通知设置失败');
|
||
} finally {
|
||
loading.value = false;
|
||
}
|
||
};
|
||
|
||
const handleSaveEmail = async () => {
|
||
if (!emailFormRef.value) return;
|
||
|
||
try {
|
||
await emailFormRef.value.validate();
|
||
saveLoading.value = true;
|
||
|
||
// 过滤空的邮箱地址
|
||
const filteredEmails = emailForm.adminEmails.filter(email => email.trim());
|
||
|
||
const updateData: UpdateNotificationSettingsParams = {
|
||
type: 'email',
|
||
config: {
|
||
...emailForm,
|
||
adminEmails: filteredEmails,
|
||
},
|
||
};
|
||
|
||
await updateNotificationSettingsApi(updateData);
|
||
ElMessage.success('邮件通知设置保存成功');
|
||
} catch (error) {
|
||
ElMessage.error('保存失败');
|
||
} finally {
|
||
saveLoading.value = false;
|
||
}
|
||
};
|
||
|
||
const handleSaveSms = async () => {
|
||
if (!smsFormRef.value) return;
|
||
|
||
try {
|
||
await smsFormRef.value.validate();
|
||
saveLoading.value = true;
|
||
|
||
// 过滤空的手机号
|
||
const filteredPhones = smsForm.adminPhones.filter(phone => phone.trim());
|
||
|
||
const updateData: UpdateNotificationSettingsParams = {
|
||
type: 'sms',
|
||
config: {
|
||
...smsForm,
|
||
adminPhones: filteredPhones,
|
||
},
|
||
};
|
||
|
||
await updateNotificationSettingsApi(updateData);
|
||
ElMessage.success('短信通知设置保存成功');
|
||
} catch (error) {
|
||
ElMessage.error('保存失败');
|
||
} finally {
|
||
saveLoading.value = false;
|
||
}
|
||
};
|
||
|
||
const handleSaveSystem = async () => {
|
||
if (!systemFormRef.value) return;
|
||
|
||
try {
|
||
await systemFormRef.value.validate();
|
||
saveLoading.value = true;
|
||
|
||
const updateData: UpdateNotificationSettingsParams = {
|
||
type: 'system',
|
||
config: systemForm,
|
||
};
|
||
|
||
await updateNotificationSettingsApi(updateData);
|
||
ElMessage.success('站内通知设置保存成功');
|
||
} catch (error) {
|
||
ElMessage.error('保存失败');
|
||
} finally {
|
||
saveLoading.value = false;
|
||
}
|
||
};
|
||
|
||
const handleSaveWechat = async () => {
|
||
if (!wechatFormRef.value) return;
|
||
|
||
try {
|
||
await wechatFormRef.value.validate();
|
||
saveLoading.value = true;
|
||
|
||
const updateData: UpdateNotificationSettingsParams = {
|
||
type: 'wechat',
|
||
config: wechatForm,
|
||
};
|
||
|
||
await updateNotificationSettingsApi(updateData);
|
||
ElMessage.success('微信通知设置保存成功');
|
||
} catch (error) {
|
||
ElMessage.error('保存失败');
|
||
} finally {
|
||
saveLoading.value = false;
|
||
}
|
||
};
|
||
|
||
const handleResetEmail = async () => {
|
||
try {
|
||
await resetNotificationSettingsApi('email');
|
||
await loadSettings();
|
||
ElMessage.success('邮件通知设置已重置');
|
||
} catch (error) {
|
||
ElMessage.error('重置失败');
|
||
}
|
||
};
|
||
|
||
const handleResetSms = async () => {
|
||
try {
|
||
await resetNotificationSettingsApi('sms');
|
||
await loadSettings();
|
||
ElMessage.success('短信通知设置已重置');
|
||
} catch (error) {
|
||
ElMessage.error('重置失败');
|
||
}
|
||
};
|
||
|
||
const handleResetSystem = async () => {
|
||
try {
|
||
await resetNotificationSettingsApi('system');
|
||
await loadSettings();
|
||
ElMessage.success('站内通知设置已重置');
|
||
} catch (error) {
|
||
ElMessage.error('重置失败');
|
||
}
|
||
};
|
||
|
||
const handleResetWechat = async () => {
|
||
try {
|
||
await resetNotificationSettingsApi('wechat');
|
||
await loadSettings();
|
||
ElMessage.success('微信通知设置已重置');
|
||
} catch (error) {
|
||
ElMessage.error('重置失败');
|
||
}
|
||
};
|
||
|
||
const handleTestEmail = async () => {
|
||
testEmailLoading.value = true;
|
||
try {
|
||
await testNotificationApi('email');
|
||
ElMessage.success('测试邮件发送成功');
|
||
} catch (error) {
|
||
ElMessage.error('发送测试邮件失败');
|
||
} finally {
|
||
testEmailLoading.value = false;
|
||
}
|
||
};
|
||
|
||
const handleTestSms = async () => {
|
||
testSmsLoading.value = true;
|
||
try {
|
||
await testNotificationApi('sms');
|
||
ElMessage.success('测试短信发送成功');
|
||
} catch (error) {
|
||
ElMessage.error('发送测试短信失败');
|
||
} finally {
|
||
testSmsLoading.value = false;
|
||
}
|
||
};
|
||
|
||
const handleTestSystem = async () => {
|
||
testSystemLoading.value = true;
|
||
try {
|
||
await testNotificationApi('system');
|
||
ElMessage.success('测试通知发送成功');
|
||
} catch (error) {
|
||
ElMessage.error('发送测试通知失败');
|
||
} finally {
|
||
testSystemLoading.value = false;
|
||
}
|
||
};
|
||
|
||
const handleTestWechat = async () => {
|
||
testWechatLoading.value = true;
|
||
try {
|
||
await testNotificationApi('wechat');
|
||
ElMessage.success('测试微信消息发送成功');
|
||
} catch (error) {
|
||
ElMessage.error('发送测试微信消息失败');
|
||
} finally {
|
||
testWechatLoading.value = false;
|
||
}
|
||
};
|
||
|
||
// 生命周期
|
||
onMounted(() => {
|
||
loadSettings();
|
||
});
|
||
</script>
|
||
|
||
<style scoped>
|
||
.notification-settings-page {
|
||
padding: 20px;
|
||
}
|
||
|
||
.settings-container {
|
||
max-width: 1200px;
|
||
margin: 0 auto;
|
||
}
|
||
|
||
.settings-card {
|
||
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
|
||
}
|
||
|
||
.card-header {
|
||
display: flex;
|
||
align-items: center;
|
||
font-size: 16px;
|
||
font-weight: 600;
|
||
}
|
||
|
||
:deep(.el-tabs__content) {
|
||
padding: 20px;
|
||
}
|
||
|
||
:deep(.el-form-item__label) {
|
||
font-weight: 500;
|
||
}
|
||
|
||
.form-item-tip {
|
||
color: #999;
|
||
font-size: 12px;
|
||
margin-top: 4px;
|
||
line-height: 1.4;
|
||
}
|
||
|
||
.email-list-container,
|
||
.phone-list-container {
|
||
width: 100%;
|
||
}
|
||
|
||
.email-list,
|
||
.phone-list {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 8px;
|
||
}
|
||
|
||
.email-item,
|
||
.phone-item {
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
|
||
.template-config {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 12px;
|
||
}
|
||
|
||
.template-item {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 12px;
|
||
}
|
||
|
||
.template-label {
|
||
width: 80px;
|
||
font-size: 14px;
|
||
color: #666;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
:deep(.el-checkbox-group) {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 8px;
|
||
}
|
||
|
||
:deep(.el-checkbox-group .el-checkbox) {
|
||
margin-right: 0;
|
||
}
|
||
</style> |