Просмотр исходного кода

🎨 feat(ui): Enhance model dropdowns with icons in Token & Channel editors

Summary
• Added visual model icons to dropdown options in both Token (`EditToken.js`) and Channel (`EditChannel.js`) editors.

Details
1. Token Editor
   - Imported `getModelCategories` from helpers.
   - Re-built Model Limits option list to prepend the matching icon to each model label.

2. Channel Editor
   - Imported `getModelCategories`.
   - Extended model‐option construction to include icons, unifying behaviour with Token editor.
   - Maintained existing logic for merging origin options and user-selected models.

Benefits
• Provides immediate visual identification of model vendors.
• Aligns UX with existing icon usage across the application, improving consistency and clarity.
• No functional changes to data handling; purely UI/UX enhancement.

Co-authored-by: [Your Name]
t0ng7u 7 месяцев назад
Родитель
Сommit
e3ef3ace29
2 измененных файлов с 46 добавлено и 9 удалено
  1. 26 5
      web/src/pages/Channel/EditChannel.js
  2. 20 4
      web/src/pages/Token/EditToken.js

+ 26 - 5
web/src/pages/Channel/EditChannel.js

@@ -28,7 +28,7 @@ import {
   Col,
   Upload,
 } from '@douyinfe/semi-ui';
-import { getChannelModels, copy, getChannelIcon } from '../../helpers';
+import { getChannelModels, copy, getChannelIcon, getModelCategories } from '../../helpers';
 import {
   IconSave,
   IconClose,
@@ -349,14 +349,14 @@ const EditChannel = (props) => {
   useEffect(() => {
     const modelMap = new Map();
 
-    originModelOptions.forEach(option => {
+    originModelOptions.forEach((option) => {
       const v = (option.value || '').trim();
       if (!modelMap.has(v)) {
         modelMap.set(v, option);
       }
     });
 
-    inputs.models.forEach(model => {
+    inputs.models.forEach((model) => {
       const v = (model || '').trim();
       if (!modelMap.has(v)) {
         modelMap.set(v, {
@@ -367,8 +367,29 @@ const EditChannel = (props) => {
       }
     });
 
-    setModelOptions(Array.from(modelMap.values()));
-  }, [originModelOptions, inputs.models]);
+    const categories = getModelCategories(t);
+    const optionsWithIcon = Array.from(modelMap.values()).map((opt) => {
+      const modelName = opt.value;
+      let icon = null;
+      for (const [key, category] of Object.entries(categories)) {
+        if (key !== 'all' && category.filter({ model_name: modelName })) {
+          icon = category.icon;
+          break;
+        }
+      }
+      return {
+        ...opt,
+        label: (
+          <span className="flex items-center gap-1">
+            {icon}
+            {modelName}
+          </span>
+        ),
+      };
+    });
+
+    setModelOptions(optionsWithIcon);
+  }, [originModelOptions, inputs.models, t]);
 
   useEffect(() => {
     fetchModels().then();

+ 20 - 4
web/src/pages/Token/EditToken.js

@@ -7,6 +7,7 @@ import {
   timestamp2string,
   renderGroupOption,
   renderQuotaWithPrompt,
+  getModelCategories,
 } from '../../helpers';
 import {
   Button,
@@ -78,10 +79,25 @@ const EditToken = (props) => {
     let res = await API.get(`/api/user/models`);
     const { success, message, data } = res.data;
     if (success) {
-      let localModelOptions = data.map((model) => ({
-        label: model,
-        value: model,
-      }));
+      const categories = getModelCategories(t);
+      let localModelOptions = data.map((model) => {
+        let icon = null;
+        for (const [key, category] of Object.entries(categories)) {
+          if (key !== 'all' && category.filter({ model_name: model })) {
+            icon = category.icon;
+            break;
+          }
+        }
+        return {
+          label: (
+            <span className="flex items-center gap-1">
+              {icon}
+              {model}
+            </span>
+          ),
+          value: model,
+        };
+      });
       setModels(localModelOptions);
     } else {
       showError(t(message));