浏览代码

refactor(settings): reorganize subscription settings into clearer tabs

- Split the Happ and Clash/Mihomo routing sections out of Information into
  their own dedicated tabs.
- Extract the profile/branding fields (title, support URL, profile page,
  announcement, theme dir) out of the mislabeled "Subscription Title"
  divider into a new Profile tab.
- Move the Update Interval setting into Information and drop the
  single-field Intervals tab.
- Add the "profile" tab label across all locales.
MHSanaei 3 天之前
父节点
当前提交
08bc481ae3

+ 42 - 35
frontend/src/pages/settings/SubscriptionGeneralTab.tsx

@@ -1,6 +1,6 @@
 import { useMemo } from 'react';
-import { Divider, Input, InputNumber, Select, Space, Switch, Tabs } from 'antd';
-import { ClockCircleOutlined, InfoCircleOutlined, SafetyCertificateOutlined, SettingOutlined } from '@ant-design/icons';
+import { Input, InputNumber, Select, Space, Switch, Tabs } from 'antd';
+import { BranchesOutlined, IdcardOutlined, InfoCircleOutlined, NodeIndexOutlined, SafetyCertificateOutlined, SettingOutlined } from '@ant-design/icons';
 import { useTranslation } from 'react-i18next';
 import type { AllSetting } from '@/models/setting';
 import { SettingListItem } from '@/components/ui';
@@ -139,8 +139,18 @@ export default function SubscriptionGeneralTab({ allSetting, updateSetting }: Su
               </Space.Compact>
             </SettingListItem>
 
-            <Divider>{t('pages.settings.subTitle')}</Divider>
-
+            <SettingListItem paddings="small" title={t('pages.settings.subUpdates')} description={t('pages.settings.subUpdatesDesc')}>
+              <InputNumber value={allSetting.subUpdates} min={1} style={{ width: '100%' }}
+                onChange={(v) => updateSetting({ subUpdates: Number(v) || 0 })} />
+            </SettingListItem>
+          </>
+        ),
+      },
+      {
+        key: '3',
+        label: catTabLabel(<IdcardOutlined />, t('pages.settings.profile'), isMobile),
+        children: (
+          <>
             <SettingListItem paddings="small" title={t('pages.settings.subTitle')} description={t('pages.settings.subTitleDesc')}>
               <Input value={allSetting.subTitle} onChange={(e) => updateSetting({ subTitle: e.target.value })} />
             </SettingListItem>
@@ -156,7 +166,6 @@ export default function SubscriptionGeneralTab({ allSetting, updateSetting }: Su
               <Input.TextArea value={allSetting.subAnnounce}
                 onChange={(e) => updateSetting({ subAnnounce: e.target.value })} />
             </SettingListItem>
-
             <SettingListItem
               paddings="small"
               title={t('pages.settings.subThemeDir')}
@@ -176,35 +185,11 @@ export default function SubscriptionGeneralTab({ allSetting, updateSetting }: Su
               <Input value={allSetting.subThemeDir} placeholder="/etc/3x-ui/sub_templates/my-theme/"
                 onChange={(e) => updateSetting({ subThemeDir: e.target.value })} />
             </SettingListItem>
-
-            <Divider>Happ</Divider>
-
-            <SettingListItem paddings="small" title={t('pages.settings.subEnableRouting')} description={t('pages.settings.subEnableRoutingDesc')}>
-              <Switch checked={allSetting.subEnableRouting} onChange={(v) => updateSetting({ subEnableRouting: v })} />
-            </SettingListItem>
-            <SettingListItem paddings="small" title={t('pages.settings.subRoutingRules')} description={t('pages.settings.subRoutingRulesDesc')}>
-              <Input.TextArea value={allSetting.subRoutingRules} placeholder="happ://routing/add/..."
-                onChange={(e) => updateSetting({ subRoutingRules: e.target.value })} />
-            </SettingListItem>
-
-            <Divider>Clash / Mihomo</Divider>
-
-            <SettingListItem paddings="small" title={t('pages.settings.subClashEnableRouting')} description={t('pages.settings.subClashEnableRoutingDesc')}>
-              <Switch checked={allSetting.subClashEnableRouting} onChange={(v) => updateSetting({ subClashEnableRouting: v })} />
-            </SettingListItem>
-            <SettingListItem paddings="small" title={t('pages.settings.subClashRoutingRules')} description={t('pages.settings.subClashRoutingRulesDesc')}>
-              <Input.TextArea
-                value={allSetting.subClashRules}
-                rows={8}
-                placeholder={'GEOSITE,category-ir,DIRECT\nGEOIP,private,DIRECT'}
-                onChange={(e) => updateSetting({ subClashRules: e.target.value })}
-              />
-            </SettingListItem>
           </>
         ),
       },
       {
-        key: '3',
+        key: '4',
         label: catTabLabel(<SafetyCertificateOutlined />, t('pages.settings.certs'), isMobile),
         children: (
           <>
@@ -218,13 +203,35 @@ export default function SubscriptionGeneralTab({ allSetting, updateSetting }: Su
         ),
       },
       {
-        key: '4',
-        label: catTabLabel(<ClockCircleOutlined />, t('pages.settings.intervals'), isMobile),
+        key: '5',
+        label: catTabLabel(<BranchesOutlined />, 'Happ', isMobile),
         children: (
           <>
-            <SettingListItem paddings="small" title={t('pages.settings.subUpdates')} description={t('pages.settings.subUpdatesDesc')}>
-              <InputNumber value={allSetting.subUpdates} min={1} style={{ width: '100%' }}
-                onChange={(v) => updateSetting({ subUpdates: Number(v) || 0 })} />
+            <SettingListItem paddings="small" title={t('pages.settings.subEnableRouting')} description={t('pages.settings.subEnableRoutingDesc')}>
+              <Switch checked={allSetting.subEnableRouting} onChange={(v) => updateSetting({ subEnableRouting: v })} />
+            </SettingListItem>
+            <SettingListItem paddings="small" title={t('pages.settings.subRoutingRules')} description={t('pages.settings.subRoutingRulesDesc')}>
+              <Input.TextArea value={allSetting.subRoutingRules} placeholder="happ://routing/add/..."
+                onChange={(e) => updateSetting({ subRoutingRules: e.target.value })} />
+            </SettingListItem>
+          </>
+        ),
+      },
+      {
+        key: '6',
+        label: catTabLabel(<NodeIndexOutlined />, 'Clash / Mihomo', isMobile),
+        children: (
+          <>
+            <SettingListItem paddings="small" title={t('pages.settings.subClashEnableRouting')} description={t('pages.settings.subClashEnableRoutingDesc')}>
+              <Switch checked={allSetting.subClashEnableRouting} onChange={(v) => updateSetting({ subClashEnableRouting: v })} />
+            </SettingListItem>
+            <SettingListItem paddings="small" title={t('pages.settings.subClashRoutingRules')} description={t('pages.settings.subClashRoutingRulesDesc')}>
+              <Input.TextArea
+                value={allSetting.subClashRules}
+                rows={8}
+                placeholder={'GEOSITE,category-ir,DIRECT\nGEOIP,private,DIRECT'}
+                onChange={(e) => updateSetting({ subClashRules: e.target.value })}
+              />
             </SettingListItem>
           </>
         ),

+ 1 - 0
internal/web/translation/ar-EG.json

@@ -1151,6 +1151,7 @@
       "proxyAndServer": "البروكسي والسيرفر",
       "intervals": "الفترات",
       "information": "المعلومات",
+      "profile": "الملف الشخصي",
       "language": "اللغة",
       "telegramBotLanguage": "لغة بوت Telegram",
       "security": {

+ 1 - 0
internal/web/translation/en-US.json

@@ -1152,6 +1152,7 @@
       "proxyAndServer": "Proxy and Server",
       "intervals": "Intervals",
       "information": "Information",
+      "profile": "Profile",
       "language": "Language",
       "telegramBotLanguage": "Telegram Bot Language",
       "security": {

+ 1 - 0
internal/web/translation/es-ES.json

@@ -1151,6 +1151,7 @@
       "proxyAndServer": "Proxy y Servidor",
       "intervals": "Intervalos",
       "information": "Información",
+      "profile": "Perfil",
       "language": "Idioma",
       "telegramBotLanguage": "Idioma del Bot de Telegram",
       "security": {

+ 1 - 0
internal/web/translation/fa-IR.json

@@ -1151,6 +1151,7 @@
       "proxyAndServer": "پراکسی و سرور",
       "intervals": "فواصل",
       "information": "اطلاعات",
+      "profile": "پروفایل",
       "language": "زبان",
       "telegramBotLanguage": "زبان ربات تلگرام",
       "security": {

+ 1 - 0
internal/web/translation/id-ID.json

@@ -1151,6 +1151,7 @@
       "proxyAndServer": "Proxy dan Server",
       "intervals": "Interval",
       "information": "Informasi",
+      "profile": "Profil",
       "language": "Bahasa",
       "telegramBotLanguage": "Bahasa Bot Telegram",
       "security": {

+ 1 - 0
internal/web/translation/ja-JP.json

@@ -1151,6 +1151,7 @@
       "proxyAndServer": "プロキシとサーバー",
       "intervals": "間隔",
       "information": "情報",
+      "profile": "プロフィール",
       "language": "言語",
       "telegramBotLanguage": "Telegram Botの言語",
       "security": {

+ 1 - 0
internal/web/translation/pt-BR.json

@@ -1151,6 +1151,7 @@
       "proxyAndServer": "Proxy e Servidor",
       "intervals": "Intervalos",
       "information": "Informação",
+      "profile": "Perfil",
       "language": "Idioma",
       "telegramBotLanguage": "Idioma do Bot do Telegram",
       "security": {

+ 1 - 0
internal/web/translation/ru-RU.json

@@ -1151,6 +1151,7 @@
       "proxyAndServer": "Прокси и сервер",
       "intervals": "Интервалы",
       "information": "Информация",
+      "profile": "Профиль",
       "language": "Язык интерфейса",
       "telegramBotLanguage": "Язык Telegram-бота",
       "security": {

+ 1 - 0
internal/web/translation/tr-TR.json

@@ -1150,6 +1150,7 @@
       "proxyAndServer": "Proxy ve Sunucu",
       "intervals": "Aralıklar",
       "information": "Bilgi",
+      "profile": "Profil",
       "language": "Dil",
       "telegramBotLanguage": "Telegram Bot Dili",
       "security": {

+ 1 - 0
internal/web/translation/uk-UA.json

@@ -1151,6 +1151,7 @@
       "proxyAndServer": "Проксі та сервер",
       "intervals": "Інтервали",
       "information": "Інформація",
+      "profile": "Профіль",
       "language": "Мова",
       "telegramBotLanguage": "Мова Telegram-бота",
       "security": {

+ 1 - 0
internal/web/translation/vi-VN.json

@@ -1151,6 +1151,7 @@
       "proxyAndServer": "Proxy và máy chủ",
       "intervals": "Khoảng thời gian",
       "information": "Thông tin",
+      "profile": "Hồ sơ",
       "language": "Ngôn ngữ",
       "telegramBotLanguage": "Ngôn ngữ của Bot Telegram",
       "security": {

+ 1 - 0
internal/web/translation/zh-CN.json

@@ -1151,6 +1151,7 @@
       "proxyAndServer": "代理和服务器",
       "intervals": "间隔",
       "information": "信息",
+      "profile": "资料",
       "language": "语言",
       "telegramBotLanguage": "Telegram 机器人语言",
       "security": {

+ 1 - 0
internal/web/translation/zh-TW.json

@@ -1151,6 +1151,7 @@
       "proxyAndServer": "代理和伺服器",
       "intervals": "間隔",
       "information": "資訊",
+      "profile": "資料",
       "language": "語言",
       "telegramBotLanguage": "Telegram 機器人語言",
       "security": {