diff --git a/src/assets/icons/glm.svg b/src/assets/icons/glm.svg
new file mode 100644
index 0000000..d3127ee
--- /dev/null
+++ b/src/assets/icons/glm.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/kimi.svg b/src/assets/icons/kimi.svg
new file mode 100644
index 0000000..732ddea
--- /dev/null
+++ b/src/assets/icons/kimi.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/components/providers/AmpcodeSection/AmpcodeSection.tsx b/src/components/providers/AmpcodeSection/AmpcodeSection.tsx
index bce0b79..bd759c6 100644
--- a/src/components/providers/AmpcodeSection/AmpcodeSection.tsx
+++ b/src/components/providers/AmpcodeSection/AmpcodeSection.tsx
@@ -22,6 +22,7 @@ export function AmpcodeSection({
onEdit,
}: AmpcodeSectionProps) {
const { t } = useTranslation();
+ const showLoadingPlaceholder = loading && !config;
return (
<>
@@ -42,7 +43,7 @@ export function AmpcodeSection({
}
>
- {loading ? (
+ {showLoadingPlaceholder ? (
{t('common.loading')}
) : (
<>
diff --git a/src/components/providers/ProviderList.tsx b/src/components/providers/ProviderList.tsx
index 7d6ec15..856e6b2 100644
--- a/src/components/providers/ProviderList.tsx
+++ b/src/components/providers/ProviderList.tsx
@@ -34,7 +34,7 @@ export function ProviderList({
}: ProviderListProps) {
const { t } = useTranslation();
- if (loading) {
+ if (loading && items.length === 0) {
return {t('common.loading')}
;
}
diff --git a/src/pages/SystemPage.module.scss b/src/pages/SystemPage.module.scss
index 5ae8435..459b741 100644
--- a/src/pages/SystemPage.module.scss
+++ b/src/pages/SystemPage.module.scss
@@ -90,6 +90,18 @@
gap: $spacing-sm;
}
+.groupTitle {
+ display: flex;
+ align-items: center;
+ gap: $spacing-sm;
+}
+
+.groupIcon {
+ width: 18px;
+ height: 18px;
+ flex-shrink: 0;
+}
+
.modelTag {
display: inline-flex;
align-items: center;
diff --git a/src/pages/SystemPage.tsx b/src/pages/SystemPage.tsx
index d601c45..dc138c8 100644
--- a/src/pages/SystemPage.tsx
+++ b/src/pages/SystemPage.tsx
@@ -3,15 +3,32 @@ import { useTranslation } from 'react-i18next';
import { Card } from '@/components/ui/Card';
import { Button } from '@/components/ui/Button';
import { IconGithub, IconBookOpen, IconExternalLink, IconCode } from '@/components/ui/icons';
-import { useAuthStore, useConfigStore, useNotificationStore, useModelsStore } from '@/stores';
+import { useAuthStore, useConfigStore, useNotificationStore, useModelsStore, useThemeStore } from '@/stores';
import { apiKeysApi } from '@/services/api/apiKeys';
import { classifyModels } from '@/utils/models';
import { STORAGE_KEY_AUTH } from '@/utils/constants';
+import iconGemini from '@/assets/icons/gemini.svg';
+import iconClaude from '@/assets/icons/claude.svg';
+import iconOpenaiLight from '@/assets/icons/openai-light.svg';
+import iconOpenaiDark from '@/assets/icons/openai-dark.svg';
+import iconQwen from '@/assets/icons/qwen.svg';
+import iconKimi from '@/assets/icons/kimi.svg';
+import iconGlm from '@/assets/icons/glm.svg';
import styles from './SystemPage.module.scss';
+const MODEL_CATEGORY_ICONS: Record = {
+ gpt: { light: iconOpenaiLight, dark: iconOpenaiDark },
+ claude: iconClaude,
+ gemini: iconGemini,
+ qwen: iconQwen,
+ kimi: iconKimi,
+ glm: iconGlm,
+};
+
export function SystemPage() {
const { t, i18n } = useTranslation();
const { showNotification, showConfirmation } = useNotificationStore();
+ const resolvedTheme = useThemeStore((state) => state.resolvedTheme);
const auth = useAuthStore();
const config = useConfigStore((state) => state.config);
const fetchConfig = useConfigStore((state) => state.fetchConfig);
@@ -31,6 +48,13 @@ export function SystemPage() {
);
const groupedModels = useMemo(() => classifyModels(models, { otherLabel }), [models, otherLabel]);
+ const getIconForCategory = (categoryId: string): string | null => {
+ const iconEntry = MODEL_CATEGORY_ICONS[categoryId];
+ if (!iconEntry) return null;
+ if (typeof iconEntry === 'string') return iconEntry;
+ return resolvedTheme === 'dark' ? iconEntry.dark : iconEntry.light;
+ };
+
const normalizeApiKeyList = (input: any): string[] => {
if (!Array.isArray(input)) return [];
const seen = new Set();
@@ -242,26 +266,32 @@ export function SystemPage() {
{t('system_info.models_empty')}
) : (
- {groupedModels.map((group) => (
-
-
-
{group.label}
-
{t('system_info.models_count', { count: group.items.length })}
+ {groupedModels.map((group) => {
+ const iconSrc = getIconForCategory(group.id);
+ return (
+
+
+
+ {iconSrc &&

}
+
{group.label}
+
+
{t('system_info.models_count', { count: group.items.length })}
+
+
+ {group.items.map((model) => (
+
+ {model.name}
+ {model.alias && {model.alias}}
+
+ ))}
+
-
- {group.items.map((model) => (
-
- {model.name}
- {model.alias && {model.alias}}
-
- ))}
-
-
- ))}
+ );
+ })}
)}