添加网关列表页面 & 添加单价不能低于最低价格校验

This commit is contained in:
Eamon
2026-04-18 17:41:27 +08:00
parent 13be8f3270
commit e5586f06d1
8 changed files with 485 additions and 38 deletions

View File

@@ -0,0 +1,245 @@
"use client"
import { zodResolver } from "@hookform/resolvers/zod"
import { useState } from "react"
import { Controller, useForm } from "react-hook-form"
import z from "zod"
import { Button } from "@/components/ui/button"
import {
Dialog,
DialogContent,
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog"
import {
Field,
FieldError,
FieldGroup,
FieldLabel,
} from "@/components/ui/field"
import { Input } from "@/components/ui/input"
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select"
import { toast } from "sonner"
import { createGateway } from "@/actions/gateway"
const schema = z.object({
mac: z.string().regex(/^([0-9A-Fa-f]{2}[:-]){5}[0-9A-Fa-f]{2}$/, {
message: "MAC地址格式不正确请使用如 00:11:22:AA:BB:CC 或 00-11-22-AA-BB-CC 的格式"
}),
ip: z.string().regex(/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/, {
message: "IP地址格式不正确请使用如 192.168.1.1 的格式"
}),
host: z.string().regex(/^([a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$/, {
message: "域名格式不正确,请使用如 example.com 的格式"
}).or(z.literal("")),
type: z.string().optional(),
status: z.string().optional(),
})
export default function CreatePage(props: { onSuccess?: () => void }) {
const [open, setOpen] = useState(false)
const [isLoading, setIsLoading] = useState(false)
const form = useForm({
resolver: zodResolver(schema),
defaultValues: {
mac: "",
ip: "",
host: "",
type: "1",
status: "0",
},
})
const onSubmit = async (data: z.infer<typeof schema>) => {
setIsLoading(true)
try {
const payload = {
mac: data.mac.trim(),
ip: data.ip.trim(),
host: data?.host.trim(),
type: data.type ? Number(data.type) : 0,
status: data.status ? Number(data.status) : 0,
}
const res = await createGateway(payload)
if (res.success) {
toast.success("添加网关成功")
setOpen(false)
props.onSuccess?.()
form.reset()
}else {
toast.error(res.message || "添加失败")
}
} catch (error) {
console.error("添加网关失败:", error)
const message = error instanceof Error ? error.message : error
toast.error(`添加失败: ${message}`)
} finally {
setIsLoading(false)
}
}
const handleCancel = () => {
setOpen(false)
form.reset()
}
const statusOptions = [
{ value: "0", label: "离线" },
{ value: "1", label: "在线" },
]
const typeOptions = [
{ value: "1", label: "自有" },
{ value: "2", label: "白银" },
]
return (
<Dialog
open={open}
onOpenChange={newOpen => {
setOpen(newOpen)
if (!newOpen) {
form.reset()
}
}}
>
<DialogTrigger asChild>
<Button></Button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle></DialogTitle>
</DialogHeader>
<form
id="gateway-create"
onSubmit={form.handleSubmit(onSubmit)}
>
<FieldGroup>
<Controller
control={form.control}
name="mac"
render={({ field, fieldState }) => (
<Field>
<FieldLabel htmlFor="gateway-create-mac">MAC地址:</FieldLabel>
<Input
id="gateway-create-mac"
placeholder="请输入MAC地址00:11:22:33:44:55"
{...field}
aria-invalid={fieldState.invalid}
/>
{fieldState.invalid && fieldState.error && (
<FieldError errors={[fieldState.error]} />
)}
</Field>
)}
/>
<Controller
control={form.control}
name="ip"
render={({ field, fieldState }) => (
<Field>
<FieldLabel htmlFor="gateway-create-ip">IP地址:</FieldLabel>
<Input
id="gateway-create-ip"
placeholder="请输入IP地址192.168.1.1"
{...field}
aria-invalid={fieldState.invalid}
/>
{fieldState.invalid && fieldState.error && (
<FieldError errors={[fieldState.error]} />
)}
</Field>
)}
/>
<Controller
control={form.control}
name="host"
render={({ field, fieldState }) => (
<Field>
<FieldLabel htmlFor="gateway-create-host">:</FieldLabel>
<Input
id="gateway-create-host"
placeholder="请输入域名example.com"
{...field}
aria-invalid={fieldState.invalid}
/>
{fieldState.invalid && fieldState.error && (
<FieldError errors={[fieldState.error]} />
)}
</Field>
)}
/>
<Controller
control={form.control}
name="type"
render={({ field, fieldState }) => (
<Field data-invalid={fieldState.invalid}>
<FieldLabel></FieldLabel>
<Select value={field.value} onValueChange={field.onChange}>
<SelectTrigger className="w-full h-9">
<SelectValue placeholder="请选择网关类型" />
</SelectTrigger>
<SelectContent>
{typeOptions.map(option => (
<SelectItem key={option.value} value={option.value}>
{option.label}
</SelectItem>
))}
</SelectContent>
</Select>
{fieldState.invalid && fieldState.error && (
<FieldError>{fieldState.error?.message}</FieldError>
)}
</Field>
)}
/>
<Controller
control={form.control}
name="status"
render={({ field, fieldState }) => (
<Field data-invalid={fieldState.invalid}>
<FieldLabel></FieldLabel>
<Select value={field.value} onValueChange={field.onChange}>
<SelectTrigger className="w-full h-9">
<SelectValue placeholder="请选择网关状态" />
</SelectTrigger>
<SelectContent>
{statusOptions.map(option => (
<SelectItem key={option.value} value={option.value}>
{option.label}
</SelectItem>
))}
</SelectContent>
</Select>
{fieldState.invalid && fieldState.error && (
<FieldError>{fieldState.error?.message}</FieldError>
)}
</Field>
)}
/>
</FieldGroup>
</form>
<DialogFooter className="gap-2">
<Button variant="ghost" onClick={handleCancel} disabled={isLoading}>
</Button>
<Button type="submit" form="gateway-create" disabled={isLoading}>
{isLoading ? "添加中..." : "添加"}
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
)
}