201 lines
5.4 KiB
TypeScript
201 lines
5.4 KiB
TypeScript
|
|
import type { ChangeEvent } from "react"
|
|||
|
|
import {
|
|||
|
|
type Control,
|
|||
|
|
type Path,
|
|||
|
|
type UseControllerReturn,
|
|||
|
|
useController,
|
|||
|
|
} from "react-hook-form"
|
|||
|
|
import { ProductCode } from "@/lib/base"
|
|||
|
|
import {
|
|||
|
|
Field,
|
|||
|
|
FieldError,
|
|||
|
|
FieldGroup,
|
|||
|
|
FieldLabel,
|
|||
|
|
FieldLegend,
|
|||
|
|
} from "../ui/field"
|
|||
|
|
import { Input } from "../ui/input"
|
|||
|
|
import {
|
|||
|
|
Select,
|
|||
|
|
SelectContent,
|
|||
|
|
SelectItem,
|
|||
|
|
SelectTrigger,
|
|||
|
|
SelectValue,
|
|||
|
|
} from "../ui/select"
|
|||
|
|
|
|||
|
|
export function ProductCodeField<
|
|||
|
|
T extends {
|
|||
|
|
code: string
|
|||
|
|
},
|
|||
|
|
>(props: { control: Control<T>; name: Path<T>; code: ProductCode }) {
|
|||
|
|
const rt = useController(props)
|
|||
|
|
|
|||
|
|
switch (props.code) {
|
|||
|
|
case ProductCode.Short:
|
|||
|
|
return <ProductShortCode {...rt} />
|
|||
|
|
case ProductCode.Long:
|
|||
|
|
return <ProductLongCode {...rt} />
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return null
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function ProductShortCode<T extends { code: string }>(
|
|||
|
|
props: UseControllerReturn<T>,
|
|||
|
|
) {
|
|||
|
|
const { field, fieldState } = props
|
|||
|
|
|
|||
|
|
const params = new URLSearchParams(field.value)
|
|||
|
|
const setParams = (data: {
|
|||
|
|
mode?: string
|
|||
|
|
live?: string
|
|||
|
|
expire?: string
|
|||
|
|
}) => {
|
|||
|
|
if (data.mode) params.set("mode", data.mode)
|
|||
|
|
if (data.live) params.set("live", data.live)
|
|||
|
|
if (data.expire) params.set("expire", data.expire)
|
|||
|
|
field.onChange(params.toString())
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const onModeChange = (value: string) => {
|
|||
|
|
setParams({ mode: value })
|
|||
|
|
}
|
|||
|
|
const onLiveChange = (e: ChangeEvent<HTMLInputElement>) => {
|
|||
|
|
let value = e.target.value || "0"
|
|||
|
|
if (value.length > 1 && value[0] === "0") {
|
|||
|
|
value = value.substring(1, value.length)
|
|||
|
|
}
|
|||
|
|
if (!/^([0-9]+)$/.test(value)) return
|
|||
|
|
setParams({ live: value })
|
|||
|
|
}
|
|||
|
|
const onExpireChange = (e: ChangeEvent<HTMLInputElement>) => {
|
|||
|
|
let value = e.target.value || "0"
|
|||
|
|
if (value.length > 1 && value[0] === "0") {
|
|||
|
|
value = value.substring(1, value.length)
|
|||
|
|
}
|
|||
|
|
if (!/^([0-9]+)$/.test(value)) return
|
|||
|
|
setParams({ expire: value })
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return (
|
|||
|
|
<FieldLegend>
|
|||
|
|
<FieldLegend>短效套餐详情</FieldLegend>
|
|||
|
|
<FieldGroup>
|
|||
|
|
<Field>
|
|||
|
|
<FieldLabel>套餐类型</FieldLabel>
|
|||
|
|
<Select
|
|||
|
|
defaultValue={params.get("mode") ?? "quota"}
|
|||
|
|
onValueChange={onModeChange}
|
|||
|
|
>
|
|||
|
|
<SelectTrigger>
|
|||
|
|
<SelectValue placeholder="请选择套餐类型" />
|
|||
|
|
</SelectTrigger>
|
|||
|
|
<SelectContent>
|
|||
|
|
<SelectItem value="time">包时</SelectItem>
|
|||
|
|
<SelectItem value="quota">包量</SelectItem>
|
|||
|
|
</SelectContent>
|
|||
|
|
</Select>
|
|||
|
|
</Field>
|
|||
|
|
<Field>
|
|||
|
|
<FieldLabel>有效期(分钟)</FieldLabel>
|
|||
|
|
<Input
|
|||
|
|
type="number"
|
|||
|
|
value={params.get("live") ?? "0"}
|
|||
|
|
onChange={onLiveChange}
|
|||
|
|
/>
|
|||
|
|
</Field>
|
|||
|
|
{params.get("mode") === "time" && (
|
|||
|
|
<Field>
|
|||
|
|
<FieldLabel>过期时间(天)</FieldLabel>
|
|||
|
|
<Input
|
|||
|
|
type="number"
|
|||
|
|
value={params.get("expire") ?? "0"}
|
|||
|
|
onChange={onExpireChange}
|
|||
|
|
/>
|
|||
|
|
</Field>
|
|||
|
|
)}
|
|||
|
|
{fieldState.error && <FieldError errors={[fieldState.error]} />}
|
|||
|
|
</FieldGroup>
|
|||
|
|
</FieldLegend>
|
|||
|
|
)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function ProductLongCode<T extends { code: string }>(
|
|||
|
|
props: UseControllerReturn<T>,
|
|||
|
|
) {
|
|||
|
|
const { field, fieldState } = props
|
|||
|
|
|
|||
|
|
const params = new URLSearchParams(field.value)
|
|||
|
|
const setParams = (data: {
|
|||
|
|
mode?: string
|
|||
|
|
live?: string
|
|||
|
|
expire?: string
|
|||
|
|
}) => {
|
|||
|
|
if (data.mode) params.set("mode", data.mode)
|
|||
|
|
if (data.live) params.set("live", data.live)
|
|||
|
|
if (data.expire) params.set("expire", data.expire)
|
|||
|
|
field.onChange(params.toString())
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const onModeChange = (value: string) => {
|
|||
|
|
setParams({ mode: value })
|
|||
|
|
}
|
|||
|
|
const onLiveChange = (e: ChangeEvent<HTMLInputElement>) => {
|
|||
|
|
let value = e.target.value || "0"
|
|||
|
|
if (value.length > 1 && value[0] === "0") {
|
|||
|
|
value = value.substring(1, value.length)
|
|||
|
|
}
|
|||
|
|
if (!/^([0-9]+)$/.test(value)) return
|
|||
|
|
setParams({ live: value })
|
|||
|
|
}
|
|||
|
|
const onExpireChange = (e: ChangeEvent<HTMLInputElement>) => {
|
|||
|
|
let value = e.target.value || "0"
|
|||
|
|
if (value.length > 1 && value[0] === "0") {
|
|||
|
|
value = value.substring(1, value.length)
|
|||
|
|
}
|
|||
|
|
if (!/^([0-9]+)$/.test(value)) return
|
|||
|
|
setParams({ expire: value })
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return (
|
|||
|
|
<FieldLegend>
|
|||
|
|
<FieldLegend>长效套餐详情</FieldLegend>
|
|||
|
|
<FieldGroup>
|
|||
|
|
<Field>
|
|||
|
|
<FieldLabel>套餐类型</FieldLabel>
|
|||
|
|
<Select
|
|||
|
|
defaultValue={params.get("mode") ?? "quota"}
|
|||
|
|
onValueChange={onModeChange}
|
|||
|
|
>
|
|||
|
|
<SelectTrigger>
|
|||
|
|
<SelectValue placeholder="请选择套餐类型" />
|
|||
|
|
</SelectTrigger>
|
|||
|
|
<SelectContent>
|
|||
|
|
<SelectItem value="time">包时</SelectItem>
|
|||
|
|
<SelectItem value="quota">包量</SelectItem>
|
|||
|
|
</SelectContent>
|
|||
|
|
</Select>
|
|||
|
|
</Field>
|
|||
|
|
<Field>
|
|||
|
|
<FieldLabel>有效期(分钟)</FieldLabel>
|
|||
|
|
<Input
|
|||
|
|
type="number"
|
|||
|
|
value={params.get("live") ?? "0"}
|
|||
|
|
onChange={onLiveChange}
|
|||
|
|
/>
|
|||
|
|
</Field>
|
|||
|
|
{params.get("mode") === "time" && (
|
|||
|
|
<Field>
|
|||
|
|
<FieldLabel>过期时间(天)</FieldLabel>
|
|||
|
|
<Input
|
|||
|
|
type="number"
|
|||
|
|
value={params.get("expire") ?? "0"}
|
|||
|
|
onChange={onExpireChange}
|
|||
|
|
/>
|
|||
|
|
</Field>
|
|||
|
|
)}
|
|||
|
|
{fieldState.error && <FieldError errors={[fieldState.error]} />}
|
|||
|
|
</FieldGroup>
|
|||
|
|
</FieldLegend>
|
|||
|
|
)
|
|||
|
|
}
|