Enhance AssistantPage and ComponentsModelsPage with API key management improvements

- Update AssistantPage to handle API key input more securely by removing placeholder values and allowing empty submissions to retain existing keys.
- Introduce a new SecretInputField component for API key entry, improving user experience with visibility toggling and contextual hints.
- Modify ComponentsModelsPage to reflect similar API key handling, ensuring users can manage keys effectively while providing feedback on existing configurations.
- Add EditorBackButton for better navigation within the AssistantPage.
This commit is contained in:
Xin Wang
2026-06-09 12:49:18 +08:00
parent 6acbac7d3b
commit 044411edc6
2 changed files with 106 additions and 49 deletions

View File

@@ -145,7 +145,9 @@ export function ComponentsModelsPage() {
try {
// TODO: 接入真实疎通接口(按 form.interfaceType 区分调用方式)
await new Promise((resolve) => setTimeout(resolve, 900));
const reachable = Boolean(form.apiUrl.trim() && form.apiKey.trim());
const reachable = Boolean(
form.apiUrl.trim() && (form.apiKey.trim() || editingModel?.apiKey),
);
setTestResult(reachable ? "ok" : "fail");
} catch {
setTestResult("fail");
@@ -186,8 +188,8 @@ export function ComponentsModelsPage() {
type: model.type,
interfaceType: model.interfaceType,
apiUrl: model.apiUrl,
// 后端回传已打码,原样带回 → 不修改则保留旧 key(写时哨兵)
apiKey: model.apiKey,
// 编辑时不把打码占位符放入输入框;空值写回后端表示保留旧 key
apiKey: "",
});
setShowKey(false);
setTestResult("idle");
@@ -282,6 +284,7 @@ export function ComponentsModelsPage() {
}
const interfaceOptions = interfaceOptionsByType[form.type];
const hasStoredApiKey = Boolean(editingId && editingModel?.apiKey);
const canSave =
form.name.trim() && form.modelId.trim() && form.apiUrl.trim();
@@ -699,18 +702,29 @@ export function ComponentsModelsPage() {
value={form.apiKey}
type={showKey ? "text" : "password"}
onChange={(event) => updateForm("apiKey", event.target.value)}
placeholder="请输入 API Key"
placeholder={
hasStoredApiKey
? "已配置,留空则保持不变"
: "请输入 API Key"
}
autoComplete="new-password"
className="border-hairline-strong bg-background pr-10 text-foreground placeholder:text-muted-soft"
/>
<button
type="button"
onClick={() => setShowKey((value) => !value)}
className="absolute right-3 top-1/2 -translate-y-1/2 text-muted-soft transition-colors hover:text-foreground"
disabled={!form.apiKey}
className="absolute right-3 top-1/2 -translate-y-1/2 text-muted-soft transition-colors hover:text-foreground disabled:cursor-not-allowed disabled:opacity-40"
aria-label={showKey ? "隐藏 API Key" : "显示 API Key"}
>
{showKey ? <EyeOff size={16} /> : <Eye size={16} />}
</button>
</div>
{hasStoredApiKey && (
<p className="mt-2 text-xs leading-5 text-muted-foreground">
</p>
)}
</div>
</div>