/* Copyright (C) 2025 QuantumNous This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . For commercial licensing, please contact support@quantumnous.com */ import React, { useRef, useEffect } from 'react'; import { Button, Typography, Card, Avatar, Form, Radio, Toast, Tabs, TabPane } from '@douyinfe/semi-ui'; import { IconMail, IconKey, IconBell, IconLink } from '@douyinfe/semi-icons'; import { ShieldCheck, Bell, DollarSign } from 'lucide-react'; import { renderQuotaWithPrompt } from '../../../../helpers'; import CodeViewer from '../../../playground/CodeViewer'; const NotificationSettings = ({ t, notificationSettings, handleNotificationSettingChange, saveNotificationSettings }) => { const formApiRef = useRef(null); // 初始化表单值 useEffect(() => { if (formApiRef.current && notificationSettings) { formApiRef.current.setValues(notificationSettings); } }, [notificationSettings]); // 处理表单字段变化 const handleFormChange = (field, value) => { handleNotificationSettingChange(field, value); }; // 表单提交 const handleSubmit = () => { if (formApiRef.current) { formApiRef.current.validate() .then(() => { saveNotificationSettings(); }) .catch((errors) => { console.log('表单验证失败:', errors); Toast.error(t('请检查表单填写是否正确')); }); } else { saveNotificationSettings(); } }; return ( } > {/* 卡片头部 */}
{t('其他设置')}
{t('通知、价格和隐私相关设置')}
(formApiRef.current = api)} initValues={notificationSettings} onSubmit={handleSubmit} > {() => ( {/* 通知配置 Tab */} {t('通知配置')} } itemKey="notification" >
handleFormChange('warningType', value)} rules={[{ required: true, message: t('请选择通知方式') }]} > {t('邮件通知')} {t('Webhook通知')} {t('额度预警阈值')} {renderQuotaWithPrompt(notificationSettings.warningThreshold)} } placeholder={t('请输入预警额度')} data={[ { value: 100000, label: '0.2$' }, { value: 500000, label: '1$' }, { value: 1000000, label: '5$' }, { value: 5000000, label: '10$' }, ]} onChange={(val) => handleFormChange('warningThreshold', val)} prefix={} extraText={t('当剩余额度低于此数值时,系统将通过选择的方式发送通知')} style={{ width: '100%', maxWidth: '300px' }} rules={[ { required: true, message: t('请输入预警阈值') }, { validator: (rule, value) => { const numValue = Number(value); if (isNaN(numValue) || numValue <= 0) { return Promise.reject(t('预警阈值必须为正数')); } return Promise.resolve(); } } ]} /> {/* 邮件通知设置 */} {notificationSettings.warningType === 'email' && ( handleFormChange('notificationEmail', val)} prefix={} extraText={t('设置用于接收额度预警的邮箱地址,不填则使用账号绑定的邮箱')} showClear /> )} {/* Webhook通知设置 */} {notificationSettings.warningType === 'webhook' && ( <> handleFormChange('webhookUrl', val)} prefix={} extraText={t('只支持HTTPS,系统将以POST方式发送通知,请确保地址可以接收POST请求')} showClear rules={[ { required: notificationSettings.warningType === 'webhook', message: t('请输入Webhook地址') }, { pattern: /^https:\/\/.+/, message: t('Webhook地址必须以https://开头') } ]} /> handleFormChange('webhookSecret', val)} prefix={} extraText={t('密钥将以Bearer方式添加到请求头中,用于验证webhook请求的合法性')} showClear />
type: 通知类型 (quota_exceed: 额度预警)
title: 通知标题
content: 通知内容,支持 {`{{value}}`} 变量占位符
values: 按顺序替换content中的变量占位符
timestamp: Unix时间戳
)}
{/* 价格设置 Tab */} {t('价格设置')} } itemKey="pricing" >
handleFormChange('acceptUnsetModelRatioModel', value)} extraText={t('当模型没有设置价格时仍接受调用,仅当您信任该网站时使用,可能会产生高额费用')} />
{/* 隐私设置 Tab */} {t('隐私设置')} } itemKey="privacy" >
handleFormChange('recordIpLog', value)} extraText={t('开启后,仅"消费"和"错误"日志将记录您的客户端IP地址')} />
)}
); }; export default NotificationSettings;