From d8f3fa9606aaeb49f57ceec7bf60ec879b31e1b6 Mon Sep 17 00:00:00 2001 From: Jeff Gu Date: Sun, 12 Apr 2026 00:08:30 +0800 Subject: [PATCH] =?UTF-8?q?feat(api):=20=E4=BC=98=E5=8C=96=E6=A8=A1?= =?UTF-8?q?=E5=9E=8B=E9=80=89=E6=8B=A9=E9=80=BB=E8=BE=91=EF=BC=8C=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E5=8A=A8=E6=80=81=E6=9B=B4=E6=96=B0=E6=A8=A1=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/ui/autocomplete.tsx | 5 ++- frontend/src/pages/ApiTest.tsx | 36 ++++++--------------- 2 files changed, 14 insertions(+), 27 deletions(-) diff --git a/frontend/src/components/ui/autocomplete.tsx b/frontend/src/components/ui/autocomplete.tsx index 7ca1623..1440754 100644 --- a/frontend/src/components/ui/autocomplete.tsx +++ b/frontend/src/components/ui/autocomplete.tsx @@ -13,6 +13,7 @@ type AutoCompleteProps = Omit, 'valu value: string onChange: (value: string) => void options: AutoCompleteOption[] + maxOptions?: number emptyText?: string dropdownClassName?: string inputClassName?: string @@ -41,6 +42,7 @@ export const AutoCompleteInput = React.forwardRef { return options.findIndex((candidate) => candidate.value === option.value) === index }) - const filteredOptions = dedupedOptions.filter((option) => matchesOption(option, query)).slice(0, 12) + const matchedOptions = dedupedOptions.filter((option) => matchesOption(option, query)) + const filteredOptions = typeof maxOptions === 'number' ? matchedOptions.slice(0, maxOptions) : matchedOptions const handleSelect = (selectedValue: string) => { onChange(selectedValue) diff --git a/frontend/src/pages/ApiTest.tsx b/frontend/src/pages/ApiTest.tsx index 56e1ee8..ec8851d 100644 --- a/frontend/src/pages/ApiTest.tsx +++ b/frontend/src/pages/ApiTest.tsx @@ -114,33 +114,10 @@ export function ApiTest() { [apiToken, tokens, channels] ) - useEffect(() => { - if (availableModels.length === 0) { - return - } - - if (modelValue) { - return - } - - const nextModel = availableModels[0] - setModelValue(nextModel) - setRequestBody((currentBody) => { - try { - const parsedBody = JSON.parse(currentBody) - parsedBody.model = nextModel - return JSON.stringify(parsedBody, null, 2) - } catch { - return buildRequestBody(endpoint, nextModel) - } - }) - }, [availableModels]) - const handleEndpointChange = (newEndpoint: string) => { setEndpoint(newEndpoint) - const nextModel = availableModels[0] || '' - setModelValue(nextModel) - setRequestBody(buildRequestBody(newEndpoint, nextModel)) + setModelValue('') + setRequestBody(buildRequestBody(newEndpoint)) } const handleCopyResponse = async () => { @@ -167,7 +144,11 @@ export function ApiTest() { try { const parsedBody = JSON.parse(requestBody) - parsedBody.model = nextModel + if (nextModel) { + parsedBody.model = nextModel + } else { + delete parsedBody.model + } setRequestBody(JSON.stringify(parsedBody, null, 2)) } catch { setRequestBody(buildRequestBody(endpoint, nextModel)) @@ -181,6 +162,8 @@ export function ApiTest() { const parsedBody = JSON.parse(value) if (typeof parsedBody?.model === 'string') { setModelValue(parsedBody.model) + } else { + setModelValue('') } } catch { // Keep the current model selection while the JSON is temporarily invalid. @@ -289,6 +272,7 @@ export function ApiTest() { placeholder="选择或输入模型名称" inputClassName="font-mono" options={modelOptions} + maxOptions={availableModels.length} emptyText="没有匹配的模型" />