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.
This commit is contained in:
Jason committed 2026-10-04 12:58:31 +08:00
1 parent 3e60be14b9
commit 7f86dbe299
3 files changed
+65 -3

No files matched your search

@@ -15,6 +15,8 @@ interface ApiKeyInputProps {
id?: string;
/** 标签行右侧(「获取 API Key ↗」) */
labelAside?: React.ReactNode;
/** 输入框下方的说明文字 */
hint?: React.ReactNode;
}
const ApiKeyInput: React.FC<ApiKeyInputProps> = ({
@@ -26,6 +28,7 @@ const ApiKeyInput: React.FC<ApiKeyInputProps> = ({
label = "API Key",
id = "apiKey",
labelAside,
hint,
}) => {
const { t } = useTranslation();
const [showKey, setShowKey] = useState(false);
@@ -72,6 +75,7 @@ const ApiKeyInput: React.FC<ApiKeyInputProps> = ({
</button>
)}
</div>
{hint && <p className="text-caption text-fg-2">{hint}</p>}
</div>
);
};
@@ -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 (
<ApiKeyInput
@@ -60,7 +66,7 @@ export function ApiKeySection({
}
disabled={disabled ?? category === "official"}
labelAside={
shouldShowLink && websiteUrl ? (
showLink ? (
<a
href={websiteUrl}
target="_blank"
@@ -71,6 +77,7 @@ export function ApiKeySection({
</a>
) : null
}
hint={promotion || undefined}
/>
);
}
+51
View File
@@ -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<React.ComponentProps<typeof ApiKeySection>> = {},
) {
return render(
<ApiKeySection
value=""
onChange={() => {}}
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();
});
});