mirror of
https://github.com/Buriburizaem0n/admin-frontend-domain.git
synced 2026-11-04 08:50:20 +00:00
fix: resolve domain.ts type errors and SWR fetching bugs; fix vps config unmarshal issue
This commit is contained in:
1 parent
825bcb08f4
commit
1e4fae5306
16 files changed
+2513
-2057
No files matched your search
+15
-17
@@ -1,4 +1,6 @@
|
||||
import { ModeToggle } from "@/components/mode-toggle"
|
||||
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import {
|
||||
Drawer,
|
||||
DrawerClose,
|
||||
@@ -9,12 +11,24 @@ import {
|
||||
DrawerTitle,
|
||||
DrawerTrigger,
|
||||
} from "@/components/ui/drawer"
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuGroup,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuLabel,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuShortcut,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu"
|
||||
import {
|
||||
NavigationMenu,
|
||||
NavigationMenuItem,
|
||||
NavigationMenuLink,
|
||||
navigationMenuTriggerStyle,
|
||||
} from "@/components/ui/navigation-menu"
|
||||
import { IconButton } from "@/components/xui/icon-button"
|
||||
import { NzNavigationMenuLink } from "@/components/xui/navigation-menu"
|
||||
import { useAuth } from "@/hooks/useAuth"
|
||||
import { useMainStore } from "@/hooks/useMainStore"
|
||||
import { useMediaQuery } from "@/hooks/useMediaQuery"
|
||||
@@ -26,21 +40,6 @@ import { useEffect, useRef, useState } from "react"
|
||||
import { useTranslation } from "react-i18next"
|
||||
import { Link, useLocation, useNavigate } from "react-router-dom"
|
||||
|
||||
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuGroup,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuLabel,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuShortcut,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu"
|
||||
import { IconButton } from "@/components/xui/icon-button"
|
||||
import { NzNavigationMenuLink } from "@/components/xui/navigation-menu"
|
||||
|
||||
// =======================================================
|
||||
// vvvvvvvvvvv 1. 在这里为移动端菜单添加新页面 vvvvvvvvvvv
|
||||
const pages = [
|
||||
@@ -252,7 +251,7 @@ export default function Header() {
|
||||
</NavigationMenuItem>
|
||||
{/* ^^^^^^^^^^^ 2. 在这里为桌面端菜单添加新链接 ^^^^^^^^^^^ */}
|
||||
{/* ======================================================= */}
|
||||
|
||||
|
||||
<NavigationMenuItem>
|
||||
<NzNavigationMenuLink
|
||||
asChild
|
||||
@@ -428,4 +427,3 @@ function Overview() {
|
||||
</section>
|
||||
)
|
||||
}
|
||||
|
||||
+45
-15
@@ -177,11 +177,21 @@ export const NotifierCard: React.FC<NotifierCardProps> = ({ data, mutate }) => {
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>
|
||||
{form.watch("type") == 2 ? "SMTP Server (host:port)" :
|
||||
form.watch("type") == 3 ? "Bot Token" : "URL"}
|
||||
{form.watch("type") == 2
|
||||
? "SMTP Server (host:port)"
|
||||
: form.watch("type") == 3
|
||||
? "Bot Token"
|
||||
: "URL"}
|
||||
</FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field} placeholder={form.watch("type") == 3 ? "123456:ABC-DEF" : ""} />
|
||||
<Input
|
||||
{...field}
|
||||
placeholder={
|
||||
form.watch("type") == 3
|
||||
? "123456:ABC-DEF"
|
||||
: ""
|
||||
}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
@@ -234,11 +244,13 @@ export const NotifierCard: React.FC<NotifierCardProps> = ({ data, mutate }) => {
|
||||
</SelectTrigger>
|
||||
</FormControl>
|
||||
<SelectContent>
|
||||
{Object.entries(nrequestTypes).map(([k, v]) => (
|
||||
<SelectItem key={k} value={k}>
|
||||
{v}
|
||||
</SelectItem>
|
||||
))}
|
||||
{Object.entries(nrequestTypes).map(
|
||||
([k, v]) => (
|
||||
<SelectItem key={k} value={k}>
|
||||
{v}
|
||||
</SelectItem>
|
||||
),
|
||||
)}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<FormMessage />
|
||||
@@ -253,15 +265,21 @@ export const NotifierCard: React.FC<NotifierCardProps> = ({ data, mutate }) => {
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>
|
||||
{form.watch("type") == 2 ? "SMTP User:Pass" :
|
||||
form.watch("type") == 3 ? "Chat ID" : t("RequestHeader")}
|
||||
{form.watch("type") == 2
|
||||
? "SMTP User:Pass"
|
||||
: form.watch("type") == 3
|
||||
? "Chat ID"
|
||||
: t("RequestHeader")}
|
||||
</FormLabel>
|
||||
<FormControl>
|
||||
<Textarea
|
||||
className="resize-y"
|
||||
placeholder={
|
||||
form.watch("type") == 2 ? "user:pass" :
|
||||
form.watch("type") == 3 ? "123456789" : '{"User-Agent":"Nezha-Agent"}'
|
||||
form.watch("type") == 2
|
||||
? "user:pass"
|
||||
: form.watch("type") == 3
|
||||
? "123456789"
|
||||
: '{"User-Agent":"Nezha-Agent"}'
|
||||
}
|
||||
{...field}
|
||||
/>
|
||||
@@ -276,11 +294,23 @@ export const NotifierCard: React.FC<NotifierCardProps> = ({ data, mutate }) => {
|
||||
name="request_body"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{form.watch("type") == 2 ? "Recipient Email" : t("RequestBody")}</FormLabel>
|
||||
<FormLabel>
|
||||
{form.watch("type") == 2
|
||||
? "Recipient Email"
|
||||
: t("RequestBody")}
|
||||
</FormLabel>
|
||||
<FormControl>
|
||||
<Textarea
|
||||
className={form.watch("type") == 2 ? "resize-y" : "resize-y h-[240px]"}
|
||||
placeholder={form.watch("type") == 2 ? "target@example.com" : '...'}
|
||||
className={
|
||||
form.watch("type") == 2
|
||||
? "resize-y"
|
||||
: "resize-y h-[240px]"
|
||||
}
|
||||
placeholder={
|
||||
form.watch("type") == 2
|
||||
? "target@example.com"
|
||||
: "..."
|
||||
}
|
||||
{...field}
|
||||
/>
|
||||
</FormControl>
|
||||
|
||||
@@ -160,13 +160,17 @@ export const ServerConfigCard = ({ sid, menuItem = false, ...props }: ServerConf
|
||||
const onSubmit = async (values: any) => {
|
||||
let resp: ModelServerTaskResponse = {}
|
||||
try {
|
||||
values.nic_allowlist = values.nic_allowlist_raw
|
||||
? JSON.parse(values.nic_allowlist_raw)
|
||||
const submitValues = { ...values }
|
||||
submitValues.nic_allowlist = submitValues.nic_allowlist_raw
|
||||
? JSON.parse(submitValues.nic_allowlist_raw)
|
||||
: undefined
|
||||
values.hard_drive_partition_allowlist = values.hard_drive_partition_allowlist_raw
|
||||
? JSON.parse(values.hard_drive_partition_allowlist_raw)
|
||||
: undefined
|
||||
resp = await setServerConfig({ config: JSON.stringify(values), servers: [sid] })
|
||||
submitValues.hard_drive_partition_allowlist =
|
||||
submitValues.hard_drive_partition_allowlist_raw
|
||||
? JSON.parse(submitValues.hard_drive_partition_allowlist_raw)
|
||||
: undefined
|
||||
delete submitValues.nic_allowlist_raw
|
||||
delete submitValues.hard_drive_partition_allowlist_raw
|
||||
resp = await setServerConfig({ config: JSON.stringify(submitValues), servers: [sid] })
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
toast(t("Error"), {
|
||||
|
||||
+59
-29
@@ -28,7 +28,7 @@ import { conv } from "@/lib/utils"
|
||||
import { asOptionalField } from "@/lib/utils"
|
||||
import { ModelServer } from "@/types"
|
||||
import { zodResolver } from "@hookform/resolvers/zod"
|
||||
import { useState, useEffect } from "react"
|
||||
import { useEffect, useState } from "react"
|
||||
import { useForm } from "react-hook-form"
|
||||
import { useTranslation } from "react-i18next"
|
||||
import { toast } from "sonner"
|
||||
@@ -65,11 +65,13 @@ const serverFormSchema = z.object({
|
||||
},
|
||||
),
|
||||
),
|
||||
billing_data: z.object({
|
||||
registrar: asOptionalField(z.string()),
|
||||
endDate: asOptionalField(z.string()),
|
||||
notes: asOptionalField(z.string()),
|
||||
}).optional(),
|
||||
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 }) => {
|
||||
@@ -92,16 +94,16 @@ export const ServerCard: React.FC<ServerCardProps> = ({ data, mutate }) => {
|
||||
|
||||
useEffect(() => {
|
||||
const handleMessage = (e: MessageEvent) => {
|
||||
if (e.data?.type === 'NZCFG_JSON') {
|
||||
if (e.data.target === 'public_note') {
|
||||
form.setValue('public_note', e.data.payload);
|
||||
toast(t("Success"), { description: "配置已通过可视化构建器自动填入" });
|
||||
if (e.data?.type === "NZCFG_JSON") {
|
||||
if (e.data.target === "public_note") {
|
||||
form.setValue("public_note", e.data.payload)
|
||||
toast(t("Success"), { description: "配置已通过可视化构建器自动填入" })
|
||||
}
|
||||
}
|
||||
};
|
||||
window.addEventListener('message', handleMessage);
|
||||
return () => window.removeEventListener('message', handleMessage);
|
||||
}, [form, t]);
|
||||
}
|
||||
window.addEventListener("message", handleMessage)
|
||||
return () => window.removeEventListener("message", handleMessage)
|
||||
}, [form, t])
|
||||
|
||||
const onSubmit = async (values: any) => {
|
||||
try {
|
||||
@@ -255,7 +257,9 @@ export const ServerCard: React.FC<ServerCardProps> = ({ data, mutate }) => {
|
||||
)}
|
||||
/>
|
||||
<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>
|
||||
<Label className="text-xs text-muted-foreground uppercase font-bold">
|
||||
Billing & Expiry
|
||||
</Label>
|
||||
<FormField
|
||||
control={form.control as any}
|
||||
name="billing_data.registrar"
|
||||
@@ -263,7 +267,10 @@ export const ServerCard: React.FC<ServerCardProps> = ({ data, mutate }) => {
|
||||
<FormItem>
|
||||
<FormLabel>Registrar</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder="AWS / Azure /阿里云" {...field} />
|
||||
<Input
|
||||
placeholder="AWS / Azure /阿里云"
|
||||
{...field}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
@@ -276,7 +283,20 @@ export const ServerCard: React.FC<ServerCardProps> = ({ data, mutate }) => {
|
||||
<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() : '')} />
|
||||
<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>
|
||||
@@ -290,18 +310,28 @@ export const ServerCard: React.FC<ServerCardProps> = ({ data, mutate }) => {
|
||||
<FormItem>
|
||||
<FormLabel className="flex justify-between items-center w-full">
|
||||
<span>{t("Public") + t("Note")}</span>
|
||||
<a href="/dashboard/nzcfg.html" target="_blank" className="text-blue-500 hover:text-blue-700 text-xs flex items-center gap-1" onClick={(e) => {
|
||||
e.preventDefault();
|
||||
const popup = window.open('/dashboard/nzcfg.html', 'nzcfg', 'width=1000,height=800');
|
||||
if(popup) {
|
||||
const timer = setInterval(() => {
|
||||
if(popup.closed) {
|
||||
clearInterval(timer);
|
||||
}
|
||||
}, 500);
|
||||
}
|
||||
}}>
|
||||
可视化管理配置 <i className="fa-solid fa-up-right-from-square"></i>
|
||||
<a
|
||||
href="/dashboard/nzcfg.html"
|
||||
target="_blank"
|
||||
className="text-blue-500 hover:text-blue-700 text-xs flex items-center gap-1"
|
||||
onClick={(e) => {
|
||||
e.preventDefault()
|
||||
const popup = window.open(
|
||||
"/dashboard/nzcfg.html",
|
||||
"nzcfg",
|
||||
"width=1000,height=800",
|
||||
)
|
||||
if (popup) {
|
||||
const timer = setInterval(() => {
|
||||
if (popup.closed) {
|
||||
clearInterval(timer)
|
||||
}
|
||||
}, 500)
|
||||
}
|
||||
}}
|
||||
>
|
||||
可视化管理配置{" "}
|
||||
<i className="fa-solid fa-up-right-from-square"></i>
|
||||
</a>
|
||||
</FormLabel>
|
||||
<FormControl>
|
||||
|
||||
@@ -23,8 +23,7 @@ const badgeVariants = cva(
|
||||
)
|
||||
|
||||
export interface BadgeProps
|
||||
extends HTMLAttributes<HTMLDivElement>,
|
||||
VariantProps<typeof badgeVariants> {}
|
||||
extends HTMLAttributes<HTMLDivElement>, VariantProps<typeof badgeVariants> {}
|
||||
|
||||
function Badge({ className, variant, ...props }: BadgeProps) {
|
||||
return <div className={cn(badgeVariants({ variant }), className)} {...props} />
|
||||
|
||||
@@ -31,8 +31,7 @@ const buttonVariants = cva(
|
||||
)
|
||||
|
||||
export interface ButtonProps
|
||||
extends ButtonHTMLAttributes<HTMLButtonElement>,
|
||||
VariantProps<typeof buttonVariants> {
|
||||
extends ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {
|
||||
asChild?: boolean
|
||||
}
|
||||
|
||||
|
||||
@@ -67,7 +67,8 @@ const multiSelectVariants = cva(
|
||||
* Props for MultiSelect component
|
||||
*/
|
||||
interface MultiSelectProps
|
||||
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
|
||||
extends
|
||||
React.ButtonHTMLAttributes<HTMLButtonElement>,
|
||||
VariantProps<typeof multiSelectVariants> {
|
||||
/**
|
||||
* An array of option objects to be displayed in the multi-select component.
|
||||
|
||||
@@ -37,7 +37,8 @@ const sheetVariants = cva(
|
||||
)
|
||||
|
||||
interface SheetContentProps
|
||||
extends ComponentPropsWithoutRef<typeof SheetPrimitive.Content>,
|
||||
extends
|
||||
ComponentPropsWithoutRef<typeof SheetPrimitive.Content>,
|
||||
VariantProps<typeof sheetVariants> {
|
||||
setOpen: Dispatch<SetStateAction<boolean>>
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user