diff --git a/messages/en/settings.json b/messages/en/settings.json
index 6654ba5d1..5bab1013a 100644
--- a/messages/en/settings.json
+++ b/messages/en/settings.json
@@ -1150,6 +1150,7 @@
"create": "Add Provider",
"edit": "Edit Provider"
},
+ "dialogDescription": "Configure provider details and advanced settings.",
"url": {
"label": "API Address *",
"placeholder": "e.g. https://open.bigmodel.cn/api/anthropic"
@@ -1470,6 +1471,7 @@
"errors": {
"invalidUrl": "Please enter a valid API address",
"invalidWebsiteUrl": "Please enter a valid provider website URL",
+ "groupTagTooLong": "Provider group tags are too long (max {max} chars total)",
"addFailed": "Failed to add provider",
"updateFailed": "Failed to update provider",
"deleteFailed": "Failed to delete provider"
diff --git a/messages/ja/settings.json b/messages/ja/settings.json
index 23d7d5107..d3d1c5e60 100644
--- a/messages/ja/settings.json
+++ b/messages/ja/settings.json
@@ -1045,6 +1045,7 @@
"create": "プロバイダーを追加",
"edit": "プロバイダーを編集"
},
+ "dialogDescription": "プロバイダーの詳細と高度な設定を構成します。",
"url": {
"label": "API アドレス *",
"placeholder": "例: https://open.bigmodel.cn/api/anthropic"
@@ -1340,6 +1341,7 @@
"errors": {
"invalidUrl": "有効な API アドレスを入力してください",
"invalidWebsiteUrl": "有効な公式サイト URL を入力してください",
+ "groupTagTooLong": "プロバイダーグループが長すぎます(合計{max}文字まで)",
"addFailed": "プロバイダーの追加に失敗しました",
"updateFailed": "プロバイダーの更新に失敗しました",
"deleteFailed": "プロバイダーの削除に失敗しました"
diff --git a/messages/ru/settings.json b/messages/ru/settings.json
index dd248698d..ba5a032b8 100644
--- a/messages/ru/settings.json
+++ b/messages/ru/settings.json
@@ -1045,6 +1045,7 @@
"create": "Добавить провайдера",
"edit": "Редактировать провайдера"
},
+ "dialogDescription": "Настройте детали провайдера и расширенные параметры.",
"url": {
"label": "Адрес API *",
"placeholder": "например: https://open.bigmodel.cn/api/anthropic"
@@ -1340,6 +1341,7 @@
"errors": {
"invalidUrl": "Введите корректный адрес API",
"invalidWebsiteUrl": "Введите корректный адрес сайта провайдера",
+ "groupTagTooLong": "Список групп провайдера слишком длинный (макс. {max} символов всего)",
"addFailed": "Не удалось добавить провайдера",
"updateFailed": "Не удалось обновить провайдера",
"deleteFailed": "Не удалось удалить провайдера"
diff --git a/messages/zh-CN/settings.json b/messages/zh-CN/settings.json
index 9f2521247..75fc54d52 100644
--- a/messages/zh-CN/settings.json
+++ b/messages/zh-CN/settings.json
@@ -659,6 +659,7 @@
"create": "新增服务商",
"edit": "编辑服务商"
},
+ "dialogDescription": "配置供应商信息及高级设置。",
"url": {
"label": "API 地址 *",
"placeholder": "例如: https://open.bigmodel.cn/api/anthropic"
@@ -979,6 +980,7 @@
"errors": {
"invalidUrl": "请输入有效的 API 地址",
"invalidWebsiteUrl": "请输入有效的供应商官网地址",
+ "groupTagTooLong": "分组标签总长度不能超过 {max} 个字符",
"addFailed": "添加服务商失败",
"updateFailed": "更新服务商失败",
"deleteFailed": "删除服务商失败"
diff --git a/messages/zh-TW/settings.json b/messages/zh-TW/settings.json
index 258f023a9..379d6374c 100644
--- a/messages/zh-TW/settings.json
+++ b/messages/zh-TW/settings.json
@@ -1045,6 +1045,7 @@
"create": "新增供應商",
"edit": "編輯供應商"
},
+ "dialogDescription": "設定供應商資訊與進階設定。",
"url": {
"label": "API 位址 *",
"placeholder": "例如:https://open.bigmodel.cn/api/anthropic"
@@ -1346,6 +1347,7 @@
"errors": {
"invalidUrl": "請輸入有效的 API 位址",
"invalidWebsiteUrl": "請輸入有效的供應商官網",
+ "groupTagTooLong": "分組標籤總長度不能超過 {max} 個字元",
"addFailed": "新增供應商失敗",
"updateFailed": "更新供應商失敗",
"deleteFailed": "刪除供應商失敗"
diff --git a/src/app/[locale]/dashboard/_components/user/user-management-table.tsx b/src/app/[locale]/dashboard/_components/user/user-management-table.tsx
index 50e1c932c..f184a0362 100644
--- a/src/app/[locale]/dashboard/_components/user/user-management-table.tsx
+++ b/src/app/[locale]/dashboard/_components/user/user-management-table.tsx
@@ -261,12 +261,7 @@ export function UserManagementTable({
useEffect(() => {
if (!scrollResetKey) return;
- parentRef.current?.scrollTo({ top: 0 });
- // Defer measurement to next frame to ensure DOM has updated
- const rafId = requestAnimationFrame(() => {
- rowVirtualizer.measure();
- });
- return () => cancelAnimationFrame(rafId);
+ rowVirtualizer.scrollToOffset(0);
}, [scrollResetKey, rowVirtualizer]);
const quickRenewTranslations = useMemo(() => {
diff --git a/src/app/[locale]/settings/providers/_components/forms/provider-form.tsx b/src/app/[locale]/settings/providers/_components/forms/provider-form.tsx
index d241912cf..d93a90ed4 100644
--- a/src/app/[locale]/settings/providers/_components/forms/provider-form.tsx
+++ b/src/app/[locale]/settings/providers/_components/forms/provider-form.tsx
@@ -19,7 +19,7 @@ import {
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible";
-import { DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog";
+import { DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import {
@@ -41,6 +41,8 @@ import { ApiTestButton } from "./api-test-button";
import { ProxyTestButton } from "./proxy-test-button";
import { UrlPreview } from "./url-preview";
+const GROUP_TAG_MAX_TOTAL_LENGTH = 50;
+
type Mode = "create" | "edit";
interface ProviderFormProps {
@@ -295,6 +297,14 @@ export function ProviderForm({
return;
}
+ // group_tag 在 DB/schema 中限制为 varchar(50),并且后端按整串校验 max(50)
+ // 这里限制逗号拼接后的总长度,避免“UI 看似可选多标签,但保存必失败”的体验
+ const serializedGroupTag = groupTag.join(",");
+ if (serializedGroupTag.length > GROUP_TAG_MAX_TOTAL_LENGTH) {
+ toast.error(t("errors.groupTagTooLong", { max: GROUP_TAG_MAX_TOTAL_LENGTH }));
+ return;
+ }
+
// 检查 failureThreshold 是否为特殊值(0 或大于 100)
const threshold = failureThreshold ?? 5;
if (threshold === 0 || threshold > 100) {
@@ -306,6 +316,15 @@ export function ProviderForm({
performSubmit();
};
+ const handleGroupTagChange = (nextTags: string[]) => {
+ const serialized = nextTags.join(",");
+ if (serialized.length > GROUP_TAG_MAX_TOTAL_LENGTH) {
+ toast.error(t("errors.groupTagTooLong", { max: GROUP_TAG_MAX_TOTAL_LENGTH }));
+ return;
+ }
+ setGroupTag(nextTags);
+ };
+
// 实际提交逻辑
const performSubmit = () => {
// 处理模型重定向(空对象转为 null)
@@ -519,6 +538,7 @@ export function ProviderForm({
<>