diff --git a/web/classic/src/components/settings/OtherSetting.jsx b/web/classic/src/components/settings/OtherSetting.jsx index 56049093..85dbe3aa 100644 --- a/web/classic/src/components/settings/OtherSetting.jsx +++ b/web/classic/src/components/settings/OtherSetting.jsx @@ -301,9 +301,12 @@ const OtherSetting = () => { showError(message); return; } - showSuccess(t('已切换到新版前端,正在刷新页面')); + showSuccess(t('已切换到新版前端,正在跳转首页')); setTimeout(() => { - window.location.reload(); + // 新版前端的路由与经典前端不同,原地刷新当前路径会 404, + // 因此切换后重置到首页,由后端按新主题返回对应前端。 + // 使用 replace 避免在历史中留下已失效的路由,防止返回时再次 404。 + window.location.replace('/'); }, 600); } catch (error) { console.error('切换新版前端失败', error); diff --git a/web/classic/src/i18n/locales/en.json b/web/classic/src/i18n/locales/en.json index 879c4da0..688e2347 100644 --- a/web/classic/src/i18n/locales/en.json +++ b/web/classic/src/i18n/locales/en.json @@ -1361,7 +1361,7 @@ "已发起支付": "Payment initiated", "已发送到 Fluent": "Sent to Fluent", "已取消 Passkey 注册": "Passkey registration cancelled", - "已切换到新版前端,正在刷新页面": "Switched to the new frontend, refreshing page", + "已切换到新版前端,正在跳转首页": "Switched to the new frontend, redirecting to home", "已同步到渠道": "Synced to Channel", "已启用": "Enabled", "已启用 Passkey,无需密码即可登录": "Passkey enabled, login without password", diff --git a/web/classic/src/i18n/locales/fr.json b/web/classic/src/i18n/locales/fr.json index 9dc1b783..d07322de 100644 --- a/web/classic/src/i18n/locales/fr.json +++ b/web/classic/src/i18n/locales/fr.json @@ -1362,7 +1362,7 @@ "已发起支付": "Paiement initié", "已发送到 Fluent": "Envoyé à Fluent", "已取消 Passkey 注册": "Enregistrement du Passkey annulé", - "已切换到新版前端,正在刷新页面": "Passage au nouveau frontend effectué, actualisation de la page", + "已切换到新版前端,正在跳转首页": "Passage au nouveau frontend effectué, redirection vers l'accueil", "已同步到渠道": "Synced to Channel", "已启用": "Activé", "已启用 Passkey,无需密码即可登录": "Passkey activé. Connexion sans mot de passe disponible.", diff --git a/web/classic/src/i18n/locales/ja.json b/web/classic/src/i18n/locales/ja.json index d171c631..3c5ee586 100644 --- a/web/classic/src/i18n/locales/ja.json +++ b/web/classic/src/i18n/locales/ja.json @@ -1341,7 +1341,7 @@ "已发起支付": "支払いを開始しました", "已发送到 Fluent": "Fluentに送信されました", "已取消 Passkey 注册": "Passkeyの登録がキャンセルされました", - "已切换到新版前端,正在刷新页面": "新しいフロントエンドに切り替えました。ページを更新しています", + "已切换到新版前端,正在跳转首页": "新しいフロントエンドに切り替えました。ホームに移動しています", "已同步到渠道": "Synced to Channel", "已启用": "有効", "已启用 Passkey,无需密码即可登录": "Passkeyが有効になり、パスワードなしでログインできます", diff --git a/web/classic/src/i18n/locales/ru.json b/web/classic/src/i18n/locales/ru.json index 5d046c44..e050cf41 100644 --- a/web/classic/src/i18n/locales/ru.json +++ b/web/classic/src/i18n/locales/ru.json @@ -1375,7 +1375,7 @@ "已发起支付": "Оплата инициирована", "已发送到 Fluent": "Отправлено в Fluent", "已取消 Passkey 注册": "Регистрация Passkey отменена", - "已切换到新版前端,正在刷新页面": "Переключено на новый интерфейс, страница обновляется", + "已切换到新版前端,正在跳转首页": "Переключено на новый интерфейс, переход на главную", "已同步到渠道": "Synced to Channel", "已启用": "Включено", "已启用 Passkey,无需密码即可登录": "Passkey включен, вход без пароля", diff --git a/web/classic/src/i18n/locales/vi.json b/web/classic/src/i18n/locales/vi.json index ea362f92..e50117d5 100644 --- a/web/classic/src/i18n/locales/vi.json +++ b/web/classic/src/i18n/locales/vi.json @@ -1342,7 +1342,7 @@ "已发起支付": "Đã khởi tạo thanh toán", "已发送到 Fluent": "Đã gửi đến Fluent", "已取消 Passkey 注册": "Đã hủy đăng ký Passkey", - "已切换到新版前端,正在刷新页面": "Đã chuyển sang frontend mới, đang làm mới trang", + "已切换到新版前端,正在跳转首页": "Đã chuyển sang frontend mới, đang chuyển đến trang chủ", "已同步到渠道": "Synced to Channel", "已启用": "Đã bật", "已启用 Passkey,无需密码即可登录": "Đã bật Passkey, đăng nhập không cần mật khẩu", diff --git a/web/classic/src/i18n/locales/zh-CN.json b/web/classic/src/i18n/locales/zh-CN.json index dc54d239..56d1e2bf 100644 --- a/web/classic/src/i18n/locales/zh-CN.json +++ b/web/classic/src/i18n/locales/zh-CN.json @@ -1311,7 +1311,7 @@ "已停止批量测试": "已停止批量测试", "已关闭后续提醒": "已关闭后续提醒", "已分配内存": "已分配内存", - "已切换到新版前端,正在刷新页面": "已切换到新版前端,正在刷新页面", + "已切换到新版前端,正在跳转首页": "已切换到新版前端,正在跳转首页", "已切换为Assistant角色": "已切换为Assistant角色", "已切换为System角色": "已切换为System角色", "已切换至最优倍率视图,每个模型使用其最低倍率分组": "已切换至最优倍率视图,每个模型使用其最低倍率分组", diff --git a/web/classic/src/i18n/locales/zh-TW.json b/web/classic/src/i18n/locales/zh-TW.json index a22ae70c..02d8c01e 100644 --- a/web/classic/src/i18n/locales/zh-TW.json +++ b/web/classic/src/i18n/locales/zh-TW.json @@ -1338,7 +1338,7 @@ "已发起支付": "已發起支付", "已发送到 Fluent": "已發送到 Fluent", "已取消 Passkey 注册": "已取消 Passkey 註冊", - "已切换到新版前端,正在刷新页面": "已切換到新版前端,正在重新整理頁面", + "已切换到新版前端,正在跳转首页": "已切換到新版前端,正在跳轉首頁", "已同步到渠道": "已同步到管道", "已启用": "已啟用", "已启用 Passkey,无需密码即可登录": "已啟用 Passkey,無需密碼即可登錄", diff --git a/web/classic/src/i18n/locales/zh.json b/web/classic/src/i18n/locales/zh.json index dbd50138..e8d0c219 100644 --- a/web/classic/src/i18n/locales/zh.json +++ b/web/classic/src/i18n/locales/zh.json @@ -909,7 +909,7 @@ "已删除消息及其回复": "已删除消息及其回复", "已发送到 Fluent": "已发送到 Fluent", "已取消 Passkey 注册": "已取消 Passkey 注册", - "已切换到新版前端,正在刷新页面": "已切换到新版前端,正在刷新页面", + "已切换到新版前端,正在跳转首页": "已切换到新版前端,正在跳转首页", "已同步到渠道": "已同步到渠道", "已启用": "已启用", "已启用 Passkey,无需密码即可登录": "已启用 Passkey,无需密码即可登录", diff --git a/web/default/src/features/system-settings/general/system-info-section.tsx b/web/default/src/features/system-settings/general/system-info-section.tsx index d1ecbc57..fa36d7f4 100644 --- a/web/default/src/features/system-settings/general/system-info-section.tsx +++ b/web/default/src/features/system-settings/general/system-info-section.tsx @@ -126,15 +126,48 @@ export function SystemInfoSection({ defaultValues }: SystemInfoSectionProps) { >, defaultValues: normalizedDefaults, onSubmit: async (_data, changedFields) => { - for (const [key, value] of Object.entries(changedFields)) { + // 主题切换会改变后端返回的前端产物,需放到最后处理:先更新其余设置项, + // 仅当它们全部成功后才提交主题切换,避免其它设置失败时就切换了主题, + // 导致用户停留或刷新到另一套前端不存在的路由而 404。 + const entries = Object.entries(changedFields) + const themeEntry = entries.find(([key]) => key === 'theme.frontend') + const otherEntries = entries.filter(([key]) => key !== 'theme.frontend') + + let allSucceeded = true + for (const [key, value] of otherEntries) { let v = normalizeValue(value) if (key === 'ServerAddress') { v = v.replace(/\/+$/, '') } - await updateOption.mutateAsync({ + const res = await updateOption.mutateAsync({ key, value: v, }) + if (!res.success) { + allSucceeded = false + } + } + if (themeEntry && !allSucceeded) { + // Theme was not submitted; keep form state consistent with backend. + _data.theme.frontend = normalizedDefaults.theme.frontend + return + } + if (themeEntry && allSucceeded) { + const res = await updateOption.mutateAsync({ + key: themeEntry[0], + value: normalizeValue(themeEntry[1]), + }) + if (res.success) { + // 当前路由在另一套前端中并不存在,主题切换成功后重置到首页以避免 404。 + // 延时用于让表单脏状态先清除(移除 beforeunload 拦截)并展示成功提示后再刷新; + // 使用 replace 让已失效的路由不进入历史,防止返回按钮再次触发 404。 + setTimeout(() => { + window.location.replace('/') + }, 600) + } else { + // Theme update failed; revert to the last saved value. + _data.theme.frontend = normalizedDefaults.theme.frontend + } } }, })