From 7f86dbe2996eeefed367b47e7fa061473e621457 Mon Sep 17 00:00:00 2001 From: Jason Date: Sun, 4 Oct 2026 10:51:01 +0800 Subject: [PATCH] fix(providers): show the preset's promotion under the API Key field again The v7 visual pass dropped the partner promotion box together with the promoted ordering. Ordering stays by name, but the promotion text comes back as the API Key field's hint (caption, secondary text, no box), shown only when the "Get API Key" link is shown, as before. ApiKeyInput gains a generic `hint` prop for text below the input. --- .../providers/forms/ApiKeyInput.tsx | 4 ++ .../providers/forms/shared/ApiKeySection.tsx | 13 +++-- tests/components/ApiKeySection.test.tsx | 51 +++++++++++++++++++ 3 files changed, 65 insertions(+), 3 deletions(-) create mode 100644 tests/components/ApiKeySection.test.tsx diff --git a/src/components/providers/forms/ApiKeyInput.tsx b/src/components/providers/forms/ApiKeyInput.tsx index bafb6fc70..52a369080 100644 --- a/src/components/providers/forms/ApiKeyInput.tsx +++ b/src/components/providers/forms/ApiKeyInput.tsx @@ -15,6 +15,8 @@ interface ApiKeyInputProps { id?: string; /** 标签行右侧(「获取 API Key ↗」) */ labelAside?: React.ReactNode; + /** 输入框下方的说明文字 */ + hint?: React.ReactNode; } const ApiKeyInput: React.FC = ({ @@ -26,6 +28,7 @@ const ApiKeyInput: React.FC = ({ label = "API Key", id = "apiKey", labelAside, + hint, }) => { const { t } = useTranslation(); const [showKey, setShowKey] = useState(false); @@ -72,6 +75,7 @@ const ApiKeyInput: React.FC = ({ )} + {hint &&

{hint}

} ); }; diff --git a/src/components/providers/forms/shared/ApiKeySection.tsx b/src/components/providers/forms/shared/ApiKeySection.tsx index b75645156..2ba72d0cd 100644 --- a/src/components/providers/forms/shared/ApiKeySection.tsx +++ b/src/components/providers/forms/shared/ApiKeySection.tsx @@ -44,8 +44,14 @@ export function ApiKeySection({ const finalPlaceholder = placeholder || defaultPlaceholder; - // 促销框已取消(v7 不画任何推广样式);partnerPromotionKey 仍有别的判断在用,只是不再渲染。 - void partnerPromotionKey; + const showLink = shouldShowLink && Boolean(websiteUrl); + // 推广语跟着「获取 API Key」走,按输入框说明文字的样式写在框下面(v7 不画推广框) + const promotion = + showLink && partnerPromotionKey + ? t(`providerForm.partnerPromotion.${partnerPromotionKey}`, { + defaultValue: "", + }) + : ""; return ( ) : null } + hint={promotion || undefined} /> ); } diff --git a/tests/components/ApiKeySection.test.tsx b/tests/components/ApiKeySection.test.tsx new file mode 100644 index 000000000..abcd89dbb --- /dev/null +++ b/tests/components/ApiKeySection.test.tsx @@ -0,0 +1,51 @@ +import { render, screen } from "@testing-library/react"; +import { describe, expect, it, vi } from "vitest"; +import { ApiKeySection } from "@/components/providers/forms/shared/ApiKeySection"; + +// 测试的 i18n 是空资源,推广语传了 defaultValue: "" 会变成空串;这里让 t() 原样返回 key +vi.mock("react-i18next", () => ({ + useTranslation: () => ({ t: (key: string) => key }), +})); + +function renderSection( + props: Partial> = {}, +) { + return render( + {}} + category="third_party" + shouldShowLink + websiteUrl="https://example.com/keys" + partnerPromotionKey="kimi" + {...props} + />, + ); +} + +describe("ApiKeySection", () => { + it("shows the preset's promotion under the input next to the API Key link", () => { + renderSection(); + + expect( + screen.getByRole("link", { name: /providerForm\.getApiKey/ }), + ).toHaveAttribute("href", "https://example.com/keys"); + expect( + screen.getByText("providerForm.partnerPromotion.kimi"), + ).toBeInTheDocument(); + }); + + it("hides the promotion when the API Key link is hidden", () => { + renderSection({ category: "official", shouldShowLink: false }); + + expect( + screen.queryByText("providerForm.partnerPromotion.kimi"), + ).not.toBeInTheDocument(); + }); + + it("renders nothing extra for presets without a promotion", () => { + const { container } = renderSection({ partnerPromotionKey: undefined }); + + expect(container.querySelector("p")).toBeNull(); + }); +});