新增通道列表查询页面
This commit is contained in:
@@ -187,7 +187,7 @@ export default function Extract(props: ExtractProps) {
|
||||
</div>
|
||||
) : resources.map((resource, i) => (<>
|
||||
<SelectItem
|
||||
key={`${resource.id}-${i}`} value={String(resource.id)} className={`p-3`}>
|
||||
key={`${resource.id}`} value={String(resource.id)} className={`p-3`}>
|
||||
<div className={`flex flex-col gap-2 w-72`}>
|
||||
{resource.type === 1 && resource.pss.type === 1 && (<>
|
||||
<div className={`flex gap-2 items-center bg-green-50 w-fit px-2 py-1 rounded-md text-sm`}>
|
||||
|
||||
@@ -35,7 +35,7 @@ export default function DataTable<T extends Record<string, unknown>>(props: Data
|
||||
|
||||
return (<>
|
||||
{/* 数据表*/}
|
||||
<div className={`border rounded-md relative bg-card`}>
|
||||
<div className={`rounded-md relative bg-card`}>
|
||||
<TableRoot>
|
||||
<TableHeader>
|
||||
{table.getHeaderGroups().map(group => (
|
||||
|
||||
@@ -35,7 +35,7 @@ export default function DatePicker(props: DatePickerProps) {
|
||||
)}
|
||||
>
|
||||
<CalendarIcon/>
|
||||
<span className={`text-sm`}>
|
||||
<span className={merge(`text-sm`, !props.value && 'text-weak')}>
|
||||
{props.value
|
||||
? format(props.value, props.format || 'yyyy-MM-dd HH:mm:ss')
|
||||
: props.placeholder || '选择日期'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {ComponentProps, ReactNode} from 'react'
|
||||
import {ComponentProps} from 'react'
|
||||
import {merge} from '@/lib/utils'
|
||||
|
||||
export type PageProps = {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
'use client'
|
||||
|
||||
import * as LabelPrimitive from '@radix-ui/react-label'
|
||||
import {Slot} from '@radix-ui/react-slot'
|
||||
import {
|
||||
@@ -8,13 +7,13 @@ import {
|
||||
ControllerProps,
|
||||
SubmitHandler,
|
||||
FieldValues, useFormContext, FieldPath, UseFormReturn, ControllerRenderProps,
|
||||
ControllerFieldState, UseFormStateReturn, FieldError, FieldErrors, SubmitErrorHandler,
|
||||
ControllerFieldState, UseFormStateReturn, FieldError, SubmitErrorHandler,
|
||||
} from 'react-hook-form'
|
||||
|
||||
import {merge} from '@/lib/utils'
|
||||
import {Label} from '@/components/ui/label'
|
||||
|
||||
import React, {BaseSyntheticEvent, ComponentProps, createContext, ReactNode, useContext, useId} from 'react'
|
||||
import React, {ComponentProps, createContext, ReactNode, useContext, useId} from 'react'
|
||||
|
||||
type FormProps<T extends FieldValues> = {
|
||||
form: UseFormReturn<T>
|
||||
@@ -60,13 +59,6 @@ type FormFieldProps<
|
||||
}) => ReactNode
|
||||
} & Omit<ControllerProps<V, N>, 'control' | 'render'>
|
||||
|
||||
type FormFieldContext = {
|
||||
id: string
|
||||
error?: FieldError
|
||||
}
|
||||
|
||||
const FormFieldContext = createContext<FormFieldContext | null>(null)
|
||||
|
||||
function FormField<
|
||||
V extends FieldValues = FieldValues,
|
||||
N extends FieldPath<V> = FieldPath<V>,
|
||||
@@ -76,68 +68,48 @@ function FormField<
|
||||
return (
|
||||
<Controller<V, N> name={props.name} control={form.control} render={({field, fieldState, formState}) => (
|
||||
<div data-slot="form-field" className={merge('grid gap-2', props.className)}>
|
||||
<FormFieldContext value={{id: id, error: fieldState.error}}>
|
||||
{!!props.label &&
|
||||
<Label
|
||||
data-slot="form-label"
|
||||
data-fail={!!fieldState.error}
|
||||
className={merge('data-[error=true]:text-fail')}
|
||||
htmlFor={id}>
|
||||
{props.label}
|
||||
</Label>
|
||||
}
|
||||
{!!props.label &&
|
||||
<FormLabel error={fieldState.error}>
|
||||
{props.label}
|
||||
</FormLabel>
|
||||
}
|
||||
|
||||
<Slot
|
||||
data-slot="form-control"
|
||||
aria-invalid={!!fieldState.error}
|
||||
aria-describedby={
|
||||
!!fieldState.error
|
||||
? `${id}-description`
|
||||
: `${id}-description ${id}-message`
|
||||
}>
|
||||
{props.children({id, field, fieldState, formState})}
|
||||
</Slot>
|
||||
<Slot
|
||||
data-slot="form-control"
|
||||
aria-invalid={!!fieldState.error}
|
||||
aria-describedby={
|
||||
!!fieldState.error
|
||||
? `${id}-description`
|
||||
: `${id}-description ${id}-message`
|
||||
}>
|
||||
{props.children({id, field, fieldState, formState})}
|
||||
</Slot>
|
||||
|
||||
{!fieldState.error ? null : (
|
||||
<p
|
||||
data-slot="form-message"
|
||||
className={merge('text-fail text-sm')}>
|
||||
{fieldState.error?.message}
|
||||
</p>
|
||||
)}
|
||||
</FormFieldContext>
|
||||
{!fieldState.error ? null : (
|
||||
<FormMessage error={fieldState.error}/>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
)}/>
|
||||
)
|
||||
}
|
||||
|
||||
const useFormField = () => {
|
||||
const context = useContext(FormFieldContext)
|
||||
if (!context) {
|
||||
throw new Error('FormField components must be used within a FormField component')
|
||||
}
|
||||
return context
|
||||
type FormState = {
|
||||
error?: FieldError
|
||||
}
|
||||
|
||||
|
||||
function FormLabel({className, ...props}: ComponentProps<typeof LabelPrimitive.Root>) {
|
||||
const {id, error} = useFormField()
|
||||
|
||||
function FormLabel({className, id, error, ...props}: ComponentProps<typeof LabelPrimitive.Root> & FormState) {
|
||||
return (
|
||||
<Label
|
||||
data-slot="form-label"
|
||||
data-fail={!!error}
|
||||
className={merge('data-[error=true]:text-fail', className)}
|
||||
className={merge('data-[fail=true]:text-fail', className)}
|
||||
htmlFor={id}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function FormDescription({className, ...props}: ComponentProps<'p'>) {
|
||||
const {id} = useFormField()
|
||||
|
||||
function FormDescription({className, id, error, ...props}: ComponentProps<'p'> & FormState) {
|
||||
return (
|
||||
<p
|
||||
data-slot="form-description"
|
||||
@@ -148,8 +120,7 @@ function FormDescription({className, ...props}: ComponentProps<'p'>) {
|
||||
)
|
||||
}
|
||||
|
||||
function FormMessage({className, ...props}: ComponentProps<'p'>) {
|
||||
const {id, error} = useFormField()
|
||||
function FormMessage({className, id, error, ...props}: ComponentProps<'p'> & FormState) {
|
||||
const body = error ? String(error?.message ?? '') : props.children
|
||||
|
||||
if (!body) {
|
||||
|
||||
@@ -37,7 +37,7 @@ function SelectTrigger({
|
||||
data-slot="select-trigger"
|
||||
data-size={size}
|
||||
className={merge(
|
||||
'border-input data-[placeholder]:text-muted-foreground [&_svg:not([class*=\'text-\'])]:text-muted-foreground ',
|
||||
'border-input data-[placeholder]:text-weak [&_svg:not([class*=\'text-\'])]:text-muted-foreground ',
|
||||
'focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-fail/20 dark:aria-invalid:ring-fail/40 ',
|
||||
'aria-invalid:border-fail dark:bg-input/30 dark:hover:bg-input/50 flex w-fit items-center justify-between gap-2 ',
|
||||
'rounded-md border bg-transparent px-3 py-2 text-sm whitespace-nowrap transition-[color] ',
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
"use client"
|
||||
'use client'
|
||||
|
||||
import * as React from "react"
|
||||
import * as React from 'react'
|
||||
|
||||
import { merge } from "@/lib/utils"
|
||||
import {merge} from '@/lib/utils'
|
||||
|
||||
function Table({ className, ...props }: React.ComponentProps<"table">) {
|
||||
function Table({className, ...props}: React.ComponentProps<'table'>) {
|
||||
return (
|
||||
<div
|
||||
data-slot="table-container"
|
||||
@@ -12,79 +12,79 @@ function Table({ className, ...props }: React.ComponentProps<"table">) {
|
||||
>
|
||||
<table
|
||||
data-slot="table"
|
||||
className={merge("w-full caption-bottom text-sm", className)}
|
||||
className={merge('w-full caption-bottom text-sm', className)}
|
||||
{...props}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function TableHeader({ className, ...props }: React.ComponentProps<"thead">) {
|
||||
function TableHeader({className, ...props}: React.ComponentProps<'thead'>) {
|
||||
return (
|
||||
<thead
|
||||
data-slot="table-header"
|
||||
className={merge("[&_tr]:border-b", className)}
|
||||
className={merge('[&_tr]:border-b', className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function TableBody({ className, ...props }: React.ComponentProps<"tbody">) {
|
||||
function TableBody({className, ...props}: React.ComponentProps<'tbody'>) {
|
||||
return (
|
||||
<tbody
|
||||
data-slot="table-body"
|
||||
className={merge("[&_tr:last-child]:border-0", className)}
|
||||
className={merge('[&_tr:last-child]:border-0', className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function TableFooter({ className, ...props }: React.ComponentProps<"tfoot">) {
|
||||
function TableFooter({className, ...props}: React.ComponentProps<'tfoot'>) {
|
||||
return (
|
||||
<tfoot
|
||||
data-slot="table-footer"
|
||||
className={merge(
|
||||
"bg-muted/50 border-t font-medium [&>tr]:last:border-b-0",
|
||||
className
|
||||
'bg-muted/50 border-t font-medium [&>tr]:last:border-b-0',
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function TableRow({ className, ...props }: React.ComponentProps<"tr">) {
|
||||
function TableRow({className, ...props}: React.ComponentProps<'tr'>) {
|
||||
return (
|
||||
<tr
|
||||
data-slot="table-row"
|
||||
className={merge(
|
||||
"hover:bg-muted/50 data-[state=selected]:bg-muted border-b transition-colors",
|
||||
className
|
||||
'hover:bg-muted/50 data-[state=selected]:bg-muted border-b transition-colors',
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function TableHead({ className, ...props }: React.ComponentProps<"th">) {
|
||||
function TableHead({className, ...props}: React.ComponentProps<'th'>) {
|
||||
return (
|
||||
<th
|
||||
data-slot="table-head"
|
||||
className={merge(
|
||||
"text-weak h-10 px-2 text-left align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
|
||||
className
|
||||
'text-weak h-10 px-2 text-left align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]',
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function TableCell({ className, ...props }: React.ComponentProps<"td">) {
|
||||
function TableCell({className, ...props}: React.ComponentProps<'td'>) {
|
||||
return (
|
||||
<td
|
||||
data-slot="table-cell"
|
||||
className={merge(
|
||||
"p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
|
||||
className
|
||||
'p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]',
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
@@ -94,11 +94,11 @@ function TableCell({ className, ...props }: React.ComponentProps<"td">) {
|
||||
function TableCaption({
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<"caption">) {
|
||||
}: React.ComponentProps<'caption'>) {
|
||||
return (
|
||||
<caption
|
||||
data-slot="table-caption"
|
||||
className={merge("text-muted-foreground mt-4 text-sm", className)}
|
||||
className={merge('text-muted-foreground mt-4 text-sm', className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user