chore: commit pending gateway changes
This commit is contained in:
@@ -2,6 +2,7 @@ import type { BaseModelCatalogItem, IntegrationPlatform, PlatformModel, RateLimi
|
||||
import { adminPages, apiDocPages, primaryModules, workspacePages } from '../navigation';
|
||||
import { DataPanel } from './DataPanel';
|
||||
import { ModuleList } from './ModuleList';
|
||||
import { baseModelTypeText } from '../pages/admin/platform-form';
|
||||
|
||||
export function Dashboard(props: {
|
||||
baseModels: BaseModelCatalogItem[];
|
||||
@@ -66,7 +67,7 @@ export function Dashboard(props: {
|
||||
<DataPanel
|
||||
columns={['Provider', '名称', '状态', '优先级']}
|
||||
empty="暂无平台数据"
|
||||
rows={props.platforms.map((item) => [item.provider, item.name, item.status, String(item.priority)])}
|
||||
rows={props.platforms.map((item) => [item.provider, item.internalName || item.name, item.status, String(item.priority)])}
|
||||
title="平台"
|
||||
/>
|
||||
<DataPanel
|
||||
@@ -81,7 +82,7 @@ export function Dashboard(props: {
|
||||
<DataPanel
|
||||
columns={['Provider', '模型', '类型', '版本']}
|
||||
empty="暂无基准模型"
|
||||
rows={props.baseModels.map((item) => [item.providerKey, item.canonicalModelKey, item.modelType, String(item.pricingVersion)])}
|
||||
rows={props.baseModels.map((item) => [item.providerKey, item.canonicalModelKey, baseModelTypeText(item), String(item.pricingVersion)])}
|
||||
title="基准模型库"
|
||||
/>
|
||||
<DataPanel
|
||||
|
||||
@@ -13,14 +13,18 @@ const buttonVariants = cva('shButton', {
|
||||
destructive: 'shButtonDestructive',
|
||||
},
|
||||
size: {
|
||||
default: 'shButtonDefaultSize',
|
||||
xs: 'shButtonXs',
|
||||
sm: 'shButtonSm',
|
||||
md: 'shButtonMd',
|
||||
default: 'shButtonMd',
|
||||
lg: 'shButtonLg',
|
||||
xl: 'shButtonXl',
|
||||
icon: 'shButtonIcon',
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: 'default',
|
||||
size: 'default',
|
||||
size: 'md',
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
import * as React from 'react';
|
||||
import * as CheckboxPrimitive from '@radix-ui/react-checkbox';
|
||||
import { CheckIcon } from 'lucide-react';
|
||||
import { cn } from '../../lib/utils';
|
||||
|
||||
export const Checkbox = React.forwardRef<
|
||||
React.ElementRef<typeof CheckboxPrimitive.Root>,
|
||||
React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<CheckboxPrimitive.Root
|
||||
ref={ref}
|
||||
className={cn(
|
||||
'peer border-input data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground data-[state=checked]:border-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive h-3.5 w-3.5 shrink-0 rounded-[3px] border shadow-xs transition-shadow outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50',
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
<CheckboxPrimitive.Indicator className="flex items-center justify-center text-primary-foreground transition-none">
|
||||
<CheckIcon className="h-3 w-3" strokeWidth={2.5} />
|
||||
</CheckboxPrimitive.Indicator>
|
||||
</CheckboxPrimitive.Root>
|
||||
));
|
||||
|
||||
Checkbox.displayName = CheckboxPrimitive.Root.displayName;
|
||||
@@ -0,0 +1,62 @@
|
||||
import * as React from 'react';
|
||||
import { AlertTriangle } from 'lucide-react';
|
||||
import { cn } from '../../lib/utils';
|
||||
import { Button } from './button';
|
||||
|
||||
export interface ConfirmDialogProps {
|
||||
cancelLabel?: string;
|
||||
children?: React.ReactNode;
|
||||
className?: string;
|
||||
confirmLabel?: string;
|
||||
confirmVariant?: 'default' | 'destructive';
|
||||
description?: string;
|
||||
loading?: boolean;
|
||||
open: boolean;
|
||||
title: string;
|
||||
onCancel: () => void;
|
||||
onConfirm: () => void | Promise<void>;
|
||||
}
|
||||
|
||||
export function ConfirmDialog(props: ConfirmDialogProps) {
|
||||
const { onCancel, open } = props;
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!open) return undefined;
|
||||
function onKeyDown(event: KeyboardEvent) {
|
||||
if (event.key === 'Escape') onCancel();
|
||||
}
|
||||
window.addEventListener('keydown', onKeyDown);
|
||||
return () => window.removeEventListener('keydown', onKeyDown);
|
||||
}, [onCancel, open]);
|
||||
|
||||
if (!open) return null;
|
||||
|
||||
return (
|
||||
<div className="confirmDialogBackdrop" role="presentation">
|
||||
<section className={cn('confirmDialog', props.className)} role="alertdialog" aria-modal="true" aria-labelledby="confirm-dialog-title">
|
||||
<div className="confirmDialogIcon">
|
||||
<AlertTriangle size={18} />
|
||||
</div>
|
||||
<div className="confirmDialogBody">
|
||||
<strong id="confirm-dialog-title">{props.title}</strong>
|
||||
{props.description && <p>{props.description}</p>}
|
||||
{props.children}
|
||||
</div>
|
||||
<footer className="confirmDialogActions">
|
||||
<Button type="button" variant="outline" size="sm" disabled={props.loading} onClick={props.onCancel}>
|
||||
{props.cancelLabel ?? '取消'}
|
||||
</Button>
|
||||
<Button
|
||||
type="button"
|
||||
variant={props.confirmVariant ?? 'destructive'}
|
||||
size="sm"
|
||||
disabled={props.loading}
|
||||
onClick={() => void props.onConfirm()}
|
||||
>
|
||||
{props.confirmLabel ?? '确认'}
|
||||
</Button>
|
||||
</footer>
|
||||
</section>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import type { ReactNode } from 'react';
|
||||
import { cn } from '../../lib/utils';
|
||||
|
||||
export function FormItem(props: {
|
||||
children: ReactNode;
|
||||
className?: string;
|
||||
description?: ReactNode;
|
||||
label: ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<label className={cn('shFormItem', props.className)}>
|
||||
<span className="shFormItemLabel">{props.label}</span>
|
||||
{props.children}
|
||||
{props.description ? <span className="shFormItemDescription">{props.description}</span> : null}
|
||||
</label>
|
||||
);
|
||||
}
|
||||
@@ -1,9 +1,13 @@
|
||||
export * from './badge';
|
||||
export * from './button';
|
||||
export * from './card';
|
||||
export * from './checkbox';
|
||||
export * from './confirm-dialog';
|
||||
export * from './dialog';
|
||||
export * from './form-item';
|
||||
export * from './input';
|
||||
export * from './label';
|
||||
export * from './message';
|
||||
export * from './select';
|
||||
export * from './separator';
|
||||
export * from './table';
|
||||
|
||||
@@ -1,8 +1,28 @@
|
||||
import * as React from 'react';
|
||||
import { cva, type VariantProps } from 'class-variance-authority';
|
||||
import { cn } from '../../lib/utils';
|
||||
|
||||
export const Input = React.forwardRef<HTMLInputElement, React.InputHTMLAttributes<HTMLInputElement>>(
|
||||
({ className, ...props }, ref) => <input ref={ref} className={cn('shInput', className)} {...props} />,
|
||||
const inputVariants = cva('shInput', {
|
||||
variants: {
|
||||
size: {
|
||||
xs: 'shControlXs',
|
||||
sm: 'shControlSm',
|
||||
md: 'shControlMd',
|
||||
lg: 'shControlLg',
|
||||
xl: 'shControlXl',
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
size: 'md',
|
||||
},
|
||||
});
|
||||
|
||||
export interface InputProps
|
||||
extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'size'>,
|
||||
VariantProps<typeof inputVariants> {}
|
||||
|
||||
export const Input = React.forwardRef<HTMLInputElement, InputProps>(
|
||||
({ className, size, ...props }, ref) => <input ref={ref} className={cn(inputVariants({ size, className }))} {...props} />,
|
||||
);
|
||||
|
||||
Input.displayName = 'Input';
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
import * as React from 'react';
|
||||
import { AlertCircle, CheckCircle2, Info, X } from 'lucide-react';
|
||||
import { cn } from '../../lib/utils';
|
||||
import { Button } from './button';
|
||||
|
||||
export type ScreenMessageVariant = 'info' | 'success' | 'error';
|
||||
|
||||
export interface ScreenMessageProps {
|
||||
className?: string;
|
||||
duration?: number;
|
||||
message: string;
|
||||
open?: boolean;
|
||||
variant?: ScreenMessageVariant;
|
||||
onClose?: () => void;
|
||||
}
|
||||
|
||||
const iconMap: Record<ScreenMessageVariant, React.ReactNode> = {
|
||||
error: <AlertCircle size={16} />,
|
||||
info: <Info size={16} />,
|
||||
success: <CheckCircle2 size={16} />,
|
||||
};
|
||||
|
||||
export function ScreenMessage(props: ScreenMessageProps) {
|
||||
const { duration = 3600, message, onClose, open = Boolean(message), variant = 'info' } = props;
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!open || !message || duration <= 0 || !onClose) return undefined;
|
||||
const timer = window.setTimeout(onClose, duration);
|
||||
return () => window.clearTimeout(timer);
|
||||
}, [duration, message, onClose, open]);
|
||||
|
||||
if (!open || !message) return null;
|
||||
|
||||
return (
|
||||
<div className="screenMessageViewport" role="presentation">
|
||||
<div className={cn('screenMessage', `screenMessage-${variant}`, props.className)} role="alert">
|
||||
<span className="screenMessageIcon">{iconMap[variant]}</span>
|
||||
<span className="screenMessageText">{message}</span>
|
||||
{onClose && (
|
||||
<Button type="button" variant="ghost" size="icon" className="screenMessageClose" aria-label="关闭提示" onClick={onClose}>
|
||||
<X size={14} />
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,8 +1,28 @@
|
||||
import * as React from 'react';
|
||||
import { cva, type VariantProps } from 'class-variance-authority';
|
||||
import { cn } from '../../lib/utils';
|
||||
|
||||
export const Select = React.forwardRef<HTMLSelectElement, React.SelectHTMLAttributes<HTMLSelectElement>>(
|
||||
({ className, ...props }, ref) => <select ref={ref} className={cn('shInput', className)} {...props} />,
|
||||
const selectVariants = cva('shInput shSelect', {
|
||||
variants: {
|
||||
size: {
|
||||
xs: 'shControlXs',
|
||||
sm: 'shControlSm',
|
||||
md: 'shControlMd',
|
||||
lg: 'shControlLg',
|
||||
xl: 'shControlXl',
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
size: 'md',
|
||||
},
|
||||
});
|
||||
|
||||
export interface SelectProps
|
||||
extends Omit<React.SelectHTMLAttributes<HTMLSelectElement>, 'size'>,
|
||||
VariantProps<typeof selectVariants> {}
|
||||
|
||||
export const Select = React.forwardRef<HTMLSelectElement, SelectProps>(
|
||||
({ className, size, ...props }, ref) => <select ref={ref} className={cn(selectVariants({ size, className }))} {...props} />,
|
||||
);
|
||||
|
||||
Select.displayName = 'Select';
|
||||
|
||||
@@ -1,8 +1,28 @@
|
||||
import * as React from 'react';
|
||||
import { cva, type VariantProps } from 'class-variance-authority';
|
||||
import { cn } from '../../lib/utils';
|
||||
|
||||
export const Textarea = React.forwardRef<HTMLTextAreaElement, React.TextareaHTMLAttributes<HTMLTextAreaElement>>(
|
||||
({ className, ...props }, ref) => <textarea ref={ref} className={cn('shTextarea', className)} {...props} />,
|
||||
const textareaVariants = cva('shTextarea', {
|
||||
variants: {
|
||||
size: {
|
||||
xs: 'shTextareaXs',
|
||||
sm: 'shTextareaSm',
|
||||
md: 'shTextareaMd',
|
||||
lg: 'shTextareaLg',
|
||||
xl: 'shTextareaXl',
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
size: 'md',
|
||||
},
|
||||
});
|
||||
|
||||
export interface TextareaProps
|
||||
extends React.TextareaHTMLAttributes<HTMLTextAreaElement>,
|
||||
VariantProps<typeof textareaVariants> {}
|
||||
|
||||
export const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(
|
||||
({ className, size, ...props }, ref) => <textarea ref={ref} className={cn(textareaVariants({ size, className }))} {...props} />,
|
||||
);
|
||||
|
||||
Textarea.displayName = 'Textarea';
|
||||
|
||||
Reference in New Issue
Block a user