fix ui: add form validator

This commit is contained in:
musistudio
2025-08-06 21:11:44 +08:00
parent 023c045821
commit 3e1963564a
4 changed files with 27 additions and 8 deletions

View File

@@ -69,7 +69,7 @@ const getUseModel = async (req: any, tokenCount: number, config: any) => {
(p: any) => p.name.toLowerCase() === provider (p: any) => p.name.toLowerCase() === provider
); );
const finalModel = finalProvider?.models?.find( const finalModel = finalProvider?.models?.find(
(m: any) => m.name.toLowerCase() === model (m: any) => m.toLowerCase() === model
); );
if (finalProvider && finalModel) { if (finalProvider && finalModel) {
return `${finalProvider.name},${finalModel}`; return `${finalProvider.name},${finalModel}`;

View File

@@ -36,6 +36,7 @@ export function Providers() {
const [isNewProvider, setIsNewProvider] = useState<boolean>(false); const [isNewProvider, setIsNewProvider] = useState<boolean>(false);
const [providerTemplates, setProviderTemplates] = useState<ProviderType[]>([]); const [providerTemplates, setProviderTemplates] = useState<ProviderType[]>([]);
const [showApiKey, setShowApiKey] = useState<Record<number, boolean>>({}); const [showApiKey, setShowApiKey] = useState<Record<number, boolean>>({});
const [apiKeyError, setApiKeyError] = useState<string | null>(null);
const comboInputRef = useRef<HTMLInputElement>(null); const comboInputRef = useRef<HTMLInputElement>(null);
useEffect(() => { useEffect(() => {
@@ -93,11 +94,12 @@ export function Providers() {
setEditingProviderIndex(config.Providers.length); setEditingProviderIndex(config.Providers.length);
setEditingProviderData(newProvider); setEditingProviderData(newProvider);
setIsNewProvider(true); setIsNewProvider(true);
// Reset API key visibility when adding new provider // Reset API key visibility and error when adding new provider
setShowApiKey(prev => ({ setShowApiKey(prev => ({
...prev, ...prev,
[config.Providers.length]: false [config.Providers.length]: false
})); }));
setApiKeyError(null);
}; };
const handleEditProvider = (index: number) => { const handleEditProvider = (index: number) => {
@@ -105,14 +107,24 @@ export function Providers() {
setEditingProviderIndex(index); setEditingProviderIndex(index);
setEditingProviderData(JSON.parse(JSON.stringify(provider))); // 深拷贝 setEditingProviderData(JSON.parse(JSON.stringify(provider))); // 深拷贝
setIsNewProvider(false); setIsNewProvider(false);
// Reset API key visibility when opening edit dialog // Reset API key visibility and error when opening edit dialog
setShowApiKey(prev => ({ setShowApiKey(prev => ({
...prev, ...prev,
[index]: false [index]: false
})); }));
setApiKeyError(null);
}; };
const handleSaveProvider = () => { const handleSaveProvider = () => {
// Validate API key
if (!editingProviderData || !editingProviderData.api_key || editingProviderData.api_key.trim() === '') {
setApiKeyError(t("providers.api_key_required"));
return;
}
// Clear error if validation passes
setApiKeyError(null);
if (editingProviderIndex !== null && editingProviderData) { if (editingProviderIndex !== null && editingProviderData) {
const newProviders = [...config.Providers]; const newProviders = [...config.Providers];
if (isNewProvider) { if (isNewProvider) {
@@ -153,6 +165,7 @@ export function Providers() {
setEditingProviderIndex(null); setEditingProviderIndex(null);
setEditingProviderData(null); setEditingProviderData(null);
setIsNewProvider(false); setIsNewProvider(false);
setApiKeyError(null);
}; };
const handleRemoveProvider = (index: number) => { const handleRemoveProvider = (index: number) => {
@@ -500,6 +513,7 @@ export function Providers() {
type={showApiKey[editingProviderIndex || 0] ? "text" : "password"} type={showApiKey[editingProviderIndex || 0] ? "text" : "password"}
value={editingProvider.api_key || ''} value={editingProvider.api_key || ''}
onChange={(e) => handleProviderChange(editingProviderIndex, 'api_key', e.target.value)} onChange={(e) => handleProviderChange(editingProviderIndex, 'api_key', e.target.value)}
className={apiKeyError ? "border-red-500" : ""}
/> />
<Button <Button
type="button" type="button"
@@ -521,6 +535,9 @@ export function Providers() {
)} )}
</Button> </Button>
</div> </div>
{apiKeyError && (
<p className="text-sm text-red-500">{apiKeyError}</p>
)}
</div> </div>
<div className="space-y-2"> <div className="space-y-2">
<Label htmlFor="models">{t("providers.models")}</Label> <Label htmlFor="models">{t("providers.models")}</Label>

View File

@@ -48,7 +48,7 @@
"providers": { "providers": {
"title": "Providers", "title": "Providers",
"name": "Name", "name": "Name",
"api_base_url": "API Base URL", "api_base_url": "API Full URL",
"api_key": "API Key", "api_key": "API Key",
"models": "Models", "models": "Models",
"models_placeholder": "Enter model name and press Enter to add", "models_placeholder": "Enter model name and press Enter to add",
@@ -80,7 +80,8 @@
"selected_transformers": "Selected Transformers", "selected_transformers": "Selected Transformers",
"import_from_template": "Import from template", "import_from_template": "Import from template",
"no_templates_found": "No templates found", "no_templates_found": "No templates found",
"select_template": "Select a template..." "select_template": "Select a template...",
"api_key_required": "API Key is required"
}, },
"router": { "router": {

View File

@@ -48,7 +48,7 @@
"providers": { "providers": {
"title": "供应商", "title": "供应商",
"name": "名称", "name": "名称",
"api_base_url": "API 基础地址", "api_base_url": "API 完整地址",
"api_key": "API 密钥", "api_key": "API 密钥",
"models": "模型", "models": "模型",
"models_placeholder": "输入模型名称并按回车键添加", "models_placeholder": "输入模型名称并按回车键添加",
@@ -80,7 +80,8 @@
"selected_transformers": "已选转换器", "selected_transformers": "已选转换器",
"import_from_template": "从模板导入", "import_from_template": "从模板导入",
"no_templates_found": "未找到模板", "no_templates_found": "未找到模板",
"select_template": "选择一个模板..." "select_template": "选择一个模板...",
"api_key_required": "API 密钥为必填项"
}, },
"router": { "router": {