-
-
-
-
- 模型配置
-
-
+
+
+
+
+ 请在 .env 中配置对应的 APIKEY,并重新启动服务
+
+
+
+
+
+
+
+
+
当前配置的模型 ({{ providerConfig.selectedModels.length }})
+
暂无配置模型
+
+
@@ -306,7 +357,7 @@
import { computed, reactive, watch, h, ref } from 'vue'
import { message } from 'ant-design-vue';
import {
- InfoCircleOutlined,
+ InfoCircleOutlined, // Keep if still used for other things, if not, remove. For now assume it might be used elsewhere.
SettingOutlined,
DownCircleOutlined,
LoadingOutlined,
@@ -479,6 +530,46 @@ const filteredModels = computed(() => {
return allModels.filter(model => model.id.toLowerCase().includes(searchQuery));
});
+// 计算不支持/已失效的模型
+const unsupportedModels = computed(() => {
+ if (providerConfig.allModels.length === 0) return [];
+ const availableIds = new Set(providerConfig.allModels.map(m => m.id));
+ return providerConfig.selectedModels.filter(id => !availableIds.has(id));
+});
+
+// 手动管理相关
+const manualModelInput = ref('');
+
+// 添加手动输入的模型
+const addManualModel = () => {
+ const val = manualModelInput.value.trim();
+ if (!val) return;
+
+ if (providerConfig.selectedModels.includes(val)) {
+ message.warning('该模型已存在');
+ return;
+ }
+
+ providerConfig.selectedModels.push(val);
+ manualModelInput.value = '';
+ message.success('添加成功');
+};
+
+// 移除模型
+const removeModel = (modelId) => {
+ const idx = providerConfig.selectedModels.indexOf(modelId);
+ if (idx > -1) {
+ providerConfig.selectedModels.splice(idx, 1);
+ }
+};
+
+// 移除所有不支持的模型
+const removeAllUnsupported = () => {
+ const toRemove = unsupportedModels.value;
+ providerConfig.selectedModels = providerConfig.selectedModels.filter(id => !toRemove.includes(id));
+ message.success(`已移除 ${toRemove.length} 个失效模型`);
+};
+
// 自定义供应商管理
const customProviderForm = ref();
const customProviderModal = reactive({
@@ -998,8 +1089,8 @@ const testCustomProvider = async (providerId, modelName) => {
}
.model-icon {
- width: 28px;
- height: 28px;
+ width: 36px;
+ height: 36px;
border-radius: 6px;
overflow: hidden;
filter: grayscale(100%);
@@ -1438,4 +1529,43 @@ const testCustomProvider = async (providerId, modelName) => {
}
}
}
+
+// Simple Notice Styles
+.simple-notice {
+ padding: 8px 12px;
+ border-radius: 4px;
+ font-size: 12px;
+ line-height: 1.5;
+ margin-bottom: 12px;
+ border: 1px solid transparent; // Keep a subtle border
+
+ &.warning {
+ background-color: var(--color-warning-50);
+ color: var(--color-warning-700);
+ border-color: var(--color-warning-100);
+ }
+
+ &.info {
+ background-color: var(--color-info-50);
+ color: var(--color-info-700);
+ border-color: var(--color-info-100);
+ }
+
+ p { // For warning message, if it's multiline
+ margin: 0;
+ }
+
+ .unsupported-list {
+ margin-top: 8px;
+ display: flex;
+ flex-wrap: wrap;
+ gap: 4px;
+ }
+ .clear-btn {
+ margin-top: 8px;
+ font-size: 12px;
+ height: 24px;
+ padding: 0 8px;
+ }
+}
diff --git a/web/src/components/UserInfoComponent.vue b/web/src/components/UserInfoComponent.vue
index e4332aee..9f7158af 100644
--- a/web/src/components/UserInfoComponent.vue
+++ b/web/src/components/UserInfoComponent.vue
@@ -395,8 +395,8 @@ const handleAvatarChange = async (info) => {
}
.user-avatar {
- width: 28px;
- height: 28px;
+ width: 32px;
+ height: 32px;
border-radius: 50%;
display: flex;
align-items: center;
@@ -406,6 +406,7 @@ const handleAvatarChange = async (info) => {
cursor: pointer;
position: relative;
overflow: hidden;
+ box-shadow: 0 2px 8px var(--shadow-2);
&:hover {
opacity: 0.9;
diff --git a/web/src/utils/modelIcon.js b/web/src/utils/modelIcon.js
index 74d1c51f..6f4544a1 100644
--- a/web/src/utils/modelIcon.js
+++ b/web/src/utils/modelIcon.js
@@ -7,6 +7,7 @@ import siliconflowIcon from '@/assets/providers/siliconflow.png'
import arkIcon from '@/assets/providers/ark.png'
import openrouterIcon from '@/assets/providers/openrouterai.png'
import defaultIcon from '@/assets/providers/default.png'
+import modelscopeIcon from '@/assets/providers/modelscope.png'
export const modelIcons = {
openai: openaiIcon,
@@ -18,5 +19,6 @@ export const modelIcons = {
ark: arkIcon,
'together.ai': togetherIcon,
openrouter: openrouterIcon,
+ modelscope: modelscopeIcon,
default: defaultIcon // 添加默认图标
}