mirror of
https://github.com/Buriburizaem0n/admin-frontend-domain.git
synced 2026-05-06 05:38:51 +00:00
feat: add billing UI, SMTP support and expiry settings
This commit is contained in:
@@ -58,6 +58,7 @@ const notificationFormSchema = z.object({
|
|||||||
verify_tls: asOptionalField(z.boolean()),
|
verify_tls: asOptionalField(z.boolean()),
|
||||||
skip_check: asOptionalField(z.boolean()),
|
skip_check: asOptionalField(z.boolean()),
|
||||||
format_metric_units: asOptionalField(z.boolean()),
|
format_metric_units: asOptionalField(z.boolean()),
|
||||||
|
type: z.coerce.number().int().default(1),
|
||||||
})
|
})
|
||||||
|
|
||||||
export const NotifierCard: React.FC<NotifierCardProps> = ({ data, mutate }) => {
|
export const NotifierCard: React.FC<NotifierCardProps> = ({ data, mutate }) => {
|
||||||
@@ -77,6 +78,7 @@ export const NotifierCard: React.FC<NotifierCardProps> = ({ data, mutate }) => {
|
|||||||
verify_tls: (data as any).verify_tls ?? false,
|
verify_tls: (data as any).verify_tls ?? false,
|
||||||
skip_check: (data as any).skip_check ?? false,
|
skip_check: (data as any).skip_check ?? false,
|
||||||
format_metric_units: (data as any).format_metric_units ?? false,
|
format_metric_units: (data as any).format_metric_units ?? false,
|
||||||
|
type: data.type ?? 1,
|
||||||
}
|
}
|
||||||
: {
|
: {
|
||||||
name: "",
|
name: "",
|
||||||
@@ -88,6 +90,7 @@ export const NotifierCard: React.FC<NotifierCardProps> = ({ data, mutate }) => {
|
|||||||
verify_tls: false,
|
verify_tls: false,
|
||||||
skip_check: false,
|
skip_check: false,
|
||||||
format_metric_units: false,
|
format_metric_units: false,
|
||||||
|
type: 1,
|
||||||
},
|
},
|
||||||
resetOptions: {
|
resetOptions: {
|
||||||
keepDefaultValues: false,
|
keepDefaultValues: false,
|
||||||
@@ -143,12 +146,36 @@ export const NotifierCard: React.FC<NotifierCardProps> = ({ data, mutate }) => {
|
|||||||
</FormItem>
|
</FormItem>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="type"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>Notification Type</FormLabel>
|
||||||
|
<Select
|
||||||
|
onValueChange={field.onChange}
|
||||||
|
value={`${field.value}`}
|
||||||
|
>
|
||||||
|
<FormControl>
|
||||||
|
<SelectTrigger>
|
||||||
|
<SelectValue />
|
||||||
|
</SelectTrigger>
|
||||||
|
</FormControl>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectItem value="1">Webhook</SelectItem>
|
||||||
|
<SelectItem value="2">SMTP (Email)</SelectItem>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
<FormField
|
<FormField
|
||||||
control={form.control}
|
control={form.control}
|
||||||
name="url"
|
name="url"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>URL</FormLabel>
|
<FormLabel>{form.watch("type") == 2 ? "SMTP Server (host:port)" : "URL"}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input {...field} />
|
<Input {...field} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
@@ -156,6 +183,8 @@ export const NotifierCard: React.FC<NotifierCardProps> = ({ data, mutate }) => {
|
|||||||
</FormItem>
|
</FormItem>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
{form.watch("type") != 2 && (
|
||||||
|
<>
|
||||||
<FormField
|
<FormField
|
||||||
control={form.control}
|
control={form.control}
|
||||||
name="request_method"
|
name="request_method"
|
||||||
@@ -212,16 +241,18 @@ export const NotifierCard: React.FC<NotifierCardProps> = ({ data, mutate }) => {
|
|||||||
</FormItem>
|
</FormItem>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
<FormField
|
<FormField
|
||||||
control={form.control}
|
control={form.control}
|
||||||
name="request_header"
|
name="request_header"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>{t("RequestHeader")}</FormLabel>
|
<FormLabel>{form.watch("type") == 2 ? "SMTP User:Pass" : t("RequestHeader")}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Textarea
|
<Textarea
|
||||||
className="resize-y"
|
className="resize-y"
|
||||||
placeholder='{"User-Agent":"Nezha-Agent"}'
|
placeholder={form.watch("type") == 2 ? "user:pass" : '{"User-Agent":"Nezha-Agent"}'}
|
||||||
{...field}
|
{...field}
|
||||||
/>
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
@@ -234,11 +265,11 @@ export const NotifierCard: React.FC<NotifierCardProps> = ({ data, mutate }) => {
|
|||||||
name="request_body"
|
name="request_body"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>{t("RequestBody")}</FormLabel>
|
<FormLabel>{form.watch("type") == 2 ? "Recipient Email" : t("RequestBody")}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Textarea
|
<Textarea
|
||||||
className="resize-y h-[240px]"
|
className={form.watch("type") == 2 ? "resize-y" : "resize-y h-[240px]"}
|
||||||
placeholder='{ "content":"#NEZHA#", "ServerName":"#SERVER.NAME#", "ServerIP":"#SERVER.IP#", "ServerIPV4":"#SERVER.IPV4#", "ServerIPV6":"#SERVER.IPV6#", "CPU":"#SERVER.CPU#", "MEM":"#SERVER.MEM#", "SWAP":"#SERVER.SWAP#", "DISK":"#SERVER.DISK#", "NetInSpeed":"#SERVER.NETINSPEED#", "NetOutSpeed":"#SERVER.NETOUTSPEED#", "TransferIn":"#SERVER.TRANSFERIN#", "TranferOut":"#SERVER.TRANSFEROUT#", "Load1":"#SERVER.LOAD1#", "Load5":"#SERVER.LOAD5#", "Load15":"#SERVER.LOAD15#", "TCP_CONN_COUNT":"#SERVER.TCPCONNCOUNT", "UDP_CONN_COUNT":"#SERVER.UDPCONNCOUNT" }'
|
placeholder={form.watch("type") == 2 ? "target@example.com" : '...'}
|
||||||
{...field}
|
{...field}
|
||||||
/>
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|||||||
@@ -65,6 +65,11 @@ const serverFormSchema = z.object({
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
billing_data: z.object({
|
||||||
|
registrar: asOptionalField(z.string()),
|
||||||
|
endDate: asOptionalField(z.string()),
|
||||||
|
notes: asOptionalField(z.string()),
|
||||||
|
}).optional(),
|
||||||
})
|
})
|
||||||
|
|
||||||
export const ServerCard: React.FC<ServerCardProps> = ({ data, mutate }) => {
|
export const ServerCard: React.FC<ServerCardProps> = ({ data, mutate }) => {
|
||||||
@@ -249,6 +254,35 @@ export const ServerCard: React.FC<ServerCardProps> = ({ data, mutate }) => {
|
|||||||
</FormItem>
|
</FormItem>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
<div className="p-3 border rounded-md border-dashed space-y-2">
|
||||||
|
<Label className="text-xs text-muted-foreground uppercase font-bold">Billing & Expiry</Label>
|
||||||
|
<FormField
|
||||||
|
control={form.control as any}
|
||||||
|
name="billing_data.registrar"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>Registrar</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<Input placeholder="AWS / Azure /阿里云" {...field} />
|
||||||
|
</FormControl>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<FormField
|
||||||
|
control={form.control as any}
|
||||||
|
name="billing_data.endDate"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>Expiry Date</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<Input type="date" {...field} value={field.value?.split('T')[0] || ''} onChange={(e) => field.onChange(e.target.value ? new Date(e.target.value).toISOString() : '')} />
|
||||||
|
</FormControl>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<FormField
|
<FormField
|
||||||
control={form.control as any}
|
control={form.control as any}
|
||||||
name="public_note"
|
name="public_note"
|
||||||
|
|||||||
@@ -151,6 +151,8 @@
|
|||||||
"AgentRealIPHeader": "Agent real IP request header",
|
"AgentRealIPHeader": "Agent real IP request header",
|
||||||
"UseDirectConnectingIP": "Use direct connection IP",
|
"UseDirectConnectingIP": "Use direct connection IP",
|
||||||
"IPChangeNotification": "IP Change Notification",
|
"IPChangeNotification": "IP Change Notification",
|
||||||
|
"IPChangeNotificationGroupID": "IP Change Notification Group ID",
|
||||||
|
"ExpiryNotificationGroupID": "Expiry Notification Group ID",
|
||||||
"FullIPNotification": "Show Full IP Address in Notification Messages",
|
"FullIPNotification": "Show Full IP Address in Notification Messages",
|
||||||
"EditService": "Edit Service",
|
"EditService": "Edit Service",
|
||||||
"CreateService": "Create Service",
|
"CreateService": "Create Service",
|
||||||
|
|||||||
@@ -158,6 +158,8 @@
|
|||||||
"AgentRealIPHeader": "Agent真实IP请求头",
|
"AgentRealIPHeader": "Agent真实IP请求头",
|
||||||
"UseDirectConnectingIP": "使用直连 IP",
|
"UseDirectConnectingIP": "使用直连 IP",
|
||||||
"IPChangeNotification": "IP 变更通知",
|
"IPChangeNotification": "IP 变更通知",
|
||||||
|
"IPChangeNotificationGroupID": "IP 变更通知组 ID",
|
||||||
|
"ExpiryNotificationGroupID": "到期通知组 ID",
|
||||||
"FullIPNotification": "在通知消息中显示完整的 IP 地址",
|
"FullIPNotification": "在通知消息中显示完整的 IP 地址",
|
||||||
"LoginFailed": "登录失败",
|
"LoginFailed": "登录失败",
|
||||||
"BruteForceAttackingToken": "暴力攻击令牌",
|
"BruteForceAttackingToken": "暴力攻击令牌",
|
||||||
|
|||||||
@@ -131,6 +131,32 @@ export default function SettingsPage() {
|
|||||||
<div>
|
<div>
|
||||||
<Form {...form}>
|
<Form {...form}>
|
||||||
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-2 my-2">
|
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-2 my-2">
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="ip_change_notification_group_id"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>{t("IPChangeNotificationGroupID")}</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<Input type="number" {...field} />
|
||||||
|
</FormControl>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="expiry_notification_group_id"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>Expiry Notification Group ID</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<Input type="number" placeholder="Enter Group ID" {...field} />
|
||||||
|
</FormControl>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
<FormField
|
<FormField
|
||||||
control={form.control}
|
control={form.control}
|
||||||
name="site_name"
|
name="site_name"
|
||||||
|
|||||||
@@ -389,6 +389,7 @@ export interface ModelNotification {
|
|||||||
created_at?: string;
|
created_at?: string;
|
||||||
id?: number;
|
id?: number;
|
||||||
name: string;
|
name: string;
|
||||||
|
type?: number;
|
||||||
request_body: string;
|
request_body: string;
|
||||||
request_header: string;
|
request_header: string;
|
||||||
request_method: number;
|
request_method: number;
|
||||||
@@ -401,6 +402,7 @@ export interface ModelNotification {
|
|||||||
export interface ModelNotificationForm {
|
export interface ModelNotificationForm {
|
||||||
/** @minLength 1 */
|
/** @minLength 1 */
|
||||||
name?: string;
|
name?: string;
|
||||||
|
type?: number;
|
||||||
request_body?: string;
|
request_body?: string;
|
||||||
request_header?: string;
|
request_header?: string;
|
||||||
request_method?: number;
|
request_method?: number;
|
||||||
@@ -464,6 +466,17 @@ export interface ModelProfileForm {
|
|||||||
reject_password?: boolean;
|
reject_password?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ModelBillingDataMod {
|
||||||
|
registrar?: string;
|
||||||
|
registeredDate?: string;
|
||||||
|
endDate?: string;
|
||||||
|
renewalPrice?: string;
|
||||||
|
autoRenewal?: string;
|
||||||
|
notes?: string;
|
||||||
|
cycle?: string;
|
||||||
|
amount?: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface ModelRule {
|
export interface ModelRule {
|
||||||
/** 覆盖范围 RuleCoverAll/IgnoreAll */
|
/** 覆盖范围 RuleCoverAll/IgnoreAll */
|
||||||
cover: number;
|
cover: number;
|
||||||
@@ -519,6 +532,7 @@ export interface ModelServer {
|
|||||||
/** 公开备注 */
|
/** 公开备注 */
|
||||||
public_note?: string;
|
public_note?: string;
|
||||||
state?: ModelHostState;
|
state?: ModelHostState;
|
||||||
|
billing_data?: ModelBillingDataMod;
|
||||||
updated_at?: string;
|
updated_at?: string;
|
||||||
uuid?: string;
|
uuid?: string;
|
||||||
}
|
}
|
||||||
@@ -546,6 +560,7 @@ export interface ModelServerForm {
|
|||||||
override_ddns_domains?: Record<string, string[]>;
|
override_ddns_domains?: Record<string, string[]>;
|
||||||
/** 公开备注 */
|
/** 公开备注 */
|
||||||
public_note?: string;
|
public_note?: string;
|
||||||
|
billing_data?: ModelBillingDataMod;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ModelServerGroup {
|
export interface ModelServerGroup {
|
||||||
@@ -655,6 +670,7 @@ export interface ModelSetting {
|
|||||||
enable_ip_change_notification?: boolean;
|
enable_ip_change_notification?: boolean;
|
||||||
/** 通知信息IP不打码 */
|
/** 通知信息IP不打码 */
|
||||||
enable_plain_ip_in_notification?: boolean;
|
enable_plain_ip_in_notification?: boolean;
|
||||||
|
expiry_notification_group_id?: number;
|
||||||
/** 特定服务器IP(多个服务器用逗号分隔) */
|
/** 特定服务器IP(多个服务器用逗号分隔) */
|
||||||
ignored_ip_notification?: string;
|
ignored_ip_notification?: string;
|
||||||
ignored_ip_notification_server_ids?: Record<string, boolean>;
|
ignored_ip_notification_server_ids?: Record<string, boolean>;
|
||||||
@@ -684,6 +700,7 @@ export interface ModelSettingForm {
|
|||||||
dns_servers?: string;
|
dns_servers?: string;
|
||||||
enable_ip_change_notification?: boolean;
|
enable_ip_change_notification?: boolean;
|
||||||
enable_plain_ip_in_notification?: boolean;
|
enable_plain_ip_in_notification?: boolean;
|
||||||
|
expiry_notification_group_id?: number;
|
||||||
ignored_ip_notification?: string;
|
ignored_ip_notification?: string;
|
||||||
install_host?: string;
|
install_host?: string;
|
||||||
/** IP变更提醒的通知组 */
|
/** IP变更提醒的通知组 */
|
||||||
|
|||||||
Reference in New Issue
Block a user