Enhance ComponentsModelsPage with FieldLabel and HelpHint components for improved form usability
Refactored the ComponentsModelsPage to introduce FieldLabel and HelpHint components, enhancing the user experience by providing contextual hints for form fields. Updated the layout to replace traditional labels with these new components, ensuring better accessibility and clarity for users when entering model details. This change aims to streamline the form interface and improve overall usability.
This commit is contained in:
@@ -7,6 +7,7 @@ import {
|
||||
ChevronRight,
|
||||
Eye,
|
||||
EyeOff,
|
||||
HelpCircle,
|
||||
Loader2,
|
||||
MoreHorizontal,
|
||||
Pencil,
|
||||
@@ -41,7 +42,12 @@ import {
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from "@/components/ui/dialog";
|
||||
import { useState } from "react";
|
||||
import {
|
||||
Popover,
|
||||
PopoverContent,
|
||||
PopoverTrigger,
|
||||
} from "@/components/ui/popover";
|
||||
import { useState, type ReactNode } from "react";
|
||||
|
||||
type ModelType = "LLM" | "ASR" | "TTS" | "Realtime" | "Embedding";
|
||||
|
||||
@@ -529,24 +535,40 @@ export function ComponentsModelsPage() {
|
||||
</DialogHeader>
|
||||
|
||||
<div className="space-y-5">
|
||||
<label className="block">
|
||||
<div className="mb-2 text-sm font-medium text-foreground">
|
||||
<div className="block">
|
||||
<FieldLabel
|
||||
htmlFor="model-name"
|
||||
hint={{
|
||||
description:
|
||||
"在控制台中展示的资源别名,便于识别和管理,可与模型 ID 不同。",
|
||||
example: "DeepSeek-V3、Qwen-Max",
|
||||
}}
|
||||
>
|
||||
资源名称
|
||||
</div>
|
||||
</FieldLabel>
|
||||
<Input
|
||||
id="model-name"
|
||||
value={form.name}
|
||||
autoFocus
|
||||
onChange={(event) => updateForm("name", event.target.value)}
|
||||
placeholder="请输入资源名称"
|
||||
className="border-hairline-strong bg-background text-foreground placeholder:text-muted-soft"
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<label className="block">
|
||||
<div className="mb-2 text-sm font-medium text-foreground">
|
||||
<div className="block">
|
||||
<FieldLabel
|
||||
htmlFor="model-id"
|
||||
hint={{
|
||||
description:
|
||||
"调用 API 时传入的模型标识,需与服务商文档中的名称完全一致。",
|
||||
example: "deepseek-chat、qwen-max、paraformer-realtime-v2",
|
||||
}}
|
||||
>
|
||||
模型 ID
|
||||
</div>
|
||||
</FieldLabel>
|
||||
<Input
|
||||
id="model-id"
|
||||
value={form.modelId}
|
||||
onChange={(event) =>
|
||||
updateForm("modelId", event.target.value)
|
||||
@@ -554,13 +576,19 @@ export function ComponentsModelsPage() {
|
||||
placeholder="例如 deepseek-chat"
|
||||
className="border-hairline-strong bg-background text-foreground placeholder:text-muted-soft"
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 gap-5 sm:grid-cols-2">
|
||||
<div className="block">
|
||||
<div className="mb-2 text-sm font-medium text-foreground">
|
||||
<FieldLabel
|
||||
hint={{
|
||||
description:
|
||||
"模型在语音管线中的能力分类,决定可选的接口类型与后续编排用途。",
|
||||
example: "LLM、ASR、TTS、Realtime、Embedding",
|
||||
}}
|
||||
>
|
||||
资源类型
|
||||
</div>
|
||||
</FieldLabel>
|
||||
<Select
|
||||
value={form.type}
|
||||
onValueChange={(value) => handleTypeChange(value as ModelType)}
|
||||
@@ -579,9 +607,15 @@ export function ComponentsModelsPage() {
|
||||
</div>
|
||||
|
||||
<div className="block">
|
||||
<div className="mb-2 text-sm font-medium text-foreground">
|
||||
<FieldLabel
|
||||
hint={{
|
||||
description:
|
||||
"服务商 API 的协议或适配器类型,需与所选资源类型匹配。",
|
||||
example: "openai、xfyun、dashscope、gemini",
|
||||
}}
|
||||
>
|
||||
接口类型
|
||||
</div>
|
||||
</FieldLabel>
|
||||
<Select
|
||||
value={form.interfaceType}
|
||||
onValueChange={(value) =>
|
||||
@@ -602,24 +636,40 @@ export function ComponentsModelsPage() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<label className="block">
|
||||
<div className="mb-2 text-sm font-medium text-foreground">
|
||||
<div className="block">
|
||||
<FieldLabel
|
||||
htmlFor="model-api-url"
|
||||
hint={{
|
||||
description:
|
||||
"模型服务的 Base URL 或接口根地址,通常以 /v1 结尾,不含具体路径参数。",
|
||||
example: "https://api.deepseek.com/v1",
|
||||
}}
|
||||
>
|
||||
API URL
|
||||
</div>
|
||||
</FieldLabel>
|
||||
<Input
|
||||
id="model-api-url"
|
||||
value={form.apiUrl}
|
||||
onChange={(event) => updateForm("apiUrl", event.target.value)}
|
||||
placeholder="https://api.example.com/v1"
|
||||
className="border-hairline-strong bg-background text-foreground placeholder:text-muted-soft"
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<label className="block">
|
||||
<div className="mb-2 text-sm font-medium text-foreground">
|
||||
<div className="block">
|
||||
<FieldLabel
|
||||
htmlFor="model-api-key"
|
||||
hint={{
|
||||
description:
|
||||
"访问模型服务的鉴权密钥,由服务商控制台生成,请妥善保管勿泄露。",
|
||||
example: "sk-xxxxxxxx",
|
||||
}}
|
||||
>
|
||||
API Key
|
||||
</div>
|
||||
</FieldLabel>
|
||||
<div className="relative">
|
||||
<Input
|
||||
id="model-api-key"
|
||||
value={form.apiKey}
|
||||
type={showKey ? "text" : "password"}
|
||||
onChange={(event) => updateForm("apiKey", event.target.value)}
|
||||
@@ -635,7 +685,7 @@ export function ComponentsModelsPage() {
|
||||
{showKey ? <EyeOff size={16} /> : <Eye size={16} />}
|
||||
</button>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<DialogFooter className="sm:items-center sm:justify-between">
|
||||
@@ -691,3 +741,54 @@ export function ComponentsModelsPage() {
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function FieldLabel({
|
||||
htmlFor,
|
||||
children,
|
||||
hint,
|
||||
}: {
|
||||
htmlFor?: string;
|
||||
children: ReactNode;
|
||||
hint: { description: string; example?: string };
|
||||
}) {
|
||||
return (
|
||||
<div className="mb-2 flex items-center gap-1.5 text-sm font-medium text-foreground">
|
||||
<label htmlFor={htmlFor}>{children}</label>
|
||||
<HelpHint {...hint} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function HelpHint({
|
||||
description,
|
||||
example,
|
||||
}: {
|
||||
description: string;
|
||||
example?: string;
|
||||
}) {
|
||||
return (
|
||||
<Popover>
|
||||
<PopoverTrigger asChild>
|
||||
<button
|
||||
type="button"
|
||||
aria-label="查看说明"
|
||||
className="flex h-5 w-5 items-center justify-center rounded-full text-muted-soft transition-colors hover:bg-surface-strong hover:text-foreground"
|
||||
>
|
||||
<HelpCircle size={14} />
|
||||
</button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent
|
||||
align="start"
|
||||
className="w-72 space-y-2 text-sm leading-6 text-muted-foreground"
|
||||
>
|
||||
<p>{description}</p>
|
||||
{example && (
|
||||
<p className="text-xs leading-5 text-muted-soft">
|
||||
<span className="font-medium text-muted-foreground">填写样例:</span>
|
||||
{example}
|
||||
</p>
|
||||
)}
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user