From 8edf71cd64f04e0280cb5af3a2e738008ec33725 Mon Sep 17 00:00:00 2001 From: matevip Date: Sat, 16 May 2026 14:51:41 +0800 Subject: [PATCH] feat(ui): dashboard model-config card + onboarding provider enablement --- mateclaw-ui/src/i18n/locales/en-US.ts | 14 +- mateclaw-ui/src/i18n/locales/zh-CN.ts | 14 +- mateclaw-ui/src/utils/providerIcons.ts | 54 ++++++ mateclaw-ui/src/views/Dashboard.vue | 180 +++++++++++++++++- .../src/views/Onboarding/StepConfigure.vue | 49 ++++- .../Models/composables/useProviderList.ts | 51 +---- 6 files changed, 300 insertions(+), 62 deletions(-) create mode 100644 mateclaw-ui/src/utils/providerIcons.ts diff --git a/mateclaw-ui/src/i18n/locales/en-US.ts b/mateclaw-ui/src/i18n/locales/en-US.ts index 8ad5eb1f..cfaebf8e 100644 --- a/mateclaw-ui/src/i18n/locales/en-US.ts +++ b/mateclaw-ui/src/i18n/locales/en-US.ts @@ -3173,7 +3173,9 @@ export default { testConnection: 'Test Connection', testSuccess: 'Connection Successful', testFailed: 'Connection Failed', - saveAndContinue: 'Save & Continue', + saveAndContinue: 'Save & Enable', + testBeforeSave: 'Test the connection first — once it passes you can enable it', + saveFailed: 'Save failed, please try again', verifyTitle: 'Verify Your Model', verifyMessage: 'Hello! Tell me briefly about yourself.', send: 'Send', @@ -3231,6 +3233,16 @@ export default { thisWeek: 'This Week', thisMonth: 'This Month', }, + models: { + title: 'Model Configuration', + subtitle: 'Enabled LLM providers and the active model.', + activeModel: 'Active model', + notSet: 'Not set', + configured: 'ready', + manage: 'Manage', + empty: 'No LLM providers enabled yet.', + emptyCta: 'Configure', + }, recentRuns: 'Recent Cron Job Runs', noRuns: 'No runs yet', runColumns: { diff --git a/mateclaw-ui/src/i18n/locales/zh-CN.ts b/mateclaw-ui/src/i18n/locales/zh-CN.ts index d2468b97..6ebe0eee 100644 --- a/mateclaw-ui/src/i18n/locales/zh-CN.ts +++ b/mateclaw-ui/src/i18n/locales/zh-CN.ts @@ -3265,7 +3265,9 @@ export default { testConnection: '测试连接', testSuccess: '连接成功', testFailed: '连接失败', - saveAndContinue: '保存并继续', + saveAndContinue: '保存并启用', + testBeforeSave: '请先测试连接,通过后即可启用', + saveFailed: '保存失败,请重试', verifyTitle: '验证你的模型', verifyMessage: '你好!简单介绍一下你自己。', send: '发送', @@ -3323,6 +3325,16 @@ export default { thisWeek: '本周', thisMonth: '本月', }, + models: { + title: '模型配置', + subtitle: '已启用的 LLM Provider 与当前生效模型。', + activeModel: '当前模型', + notSet: '未设置', + configured: '已就绪', + manage: '管理', + empty: '尚未启用任何模型 Provider。', + emptyCta: '去配置', + }, recentRuns: '最近定时任务执行', noRuns: '暂无执行记录', runColumns: { diff --git a/mateclaw-ui/src/utils/providerIcons.ts b/mateclaw-ui/src/utils/providerIcons.ts new file mode 100644 index 00000000..e75a414a --- /dev/null +++ b/mateclaw-ui/src/utils/providerIcons.ts @@ -0,0 +1,54 @@ +// Provider brand icon resolution. Icon assets live in public/icons/providers/. +// Shared by the Models settings page and the dashboard model-config card so the +// id → icon mapping has a single source of truth. + +const providerIconMap: Record = { + 'dashscope': '/icons/providers/dashscope.png', + // dashscope-compat shares the same Aliyun DashScope brand — same logo. + 'dashscope-compat': '/icons/providers/dashscope.png', + 'modelscope': '/icons/providers/modelscope.svg', + 'aliyun-codingplan': '/icons/providers/aliyun-codingplan.svg', + 'aliyun-codingplan-intl': '/icons/providers/aliyun-codingplan.svg', + // bailian-team is an Aliyun product line — reuse the aliyun mark. + 'bailian-team': '/icons/providers/aliyun-codingplan.svg', + 'openai': '/icons/providers/openai.svg', + 'azure-openai': '/icons/providers/azure-openai.svg', + 'minimax': '/icons/providers/minimax.png', + 'minimax-cn': '/icons/providers/minimax.png', + 'kimi-cn': '/icons/providers/kimi.svg', + 'kimi-intl': '/icons/providers/kimi.svg', + 'kimi-code': '/icons/providers/kimi.svg', + 'deepseek': '/icons/providers/deepseek.svg', + 'anthropic': '/icons/providers/anthropic.svg', + 'gemini': '/icons/providers/gemini.svg', + 'ollama': '/icons/providers/ollama.svg', + 'lmstudio': '/icons/providers/lmstudio.svg', + 'llamacpp': '/icons/providers/llamacpp.svg', + 'mlx': '/icons/providers/mlx.svg', + 'openrouter': '/icons/providers/openrouter.svg', + 'zhipu-cn': '/icons/providers/zhipu.svg', + 'zhipu-intl': '/icons/providers/zhipu.svg', + // Coding Plan subscription endpoints — same brand, reuse mark. + 'zhipu-cn-codingplan': '/icons/providers/zhipu.svg', + 'zhipu-intl-codingplan': '/icons/providers/zhipu.svg', + 'volcengine': '/icons/providers/volcengine.svg', + // volcengine-plan = "Volcano Engine Coding Plan" — same brand, reuse mark. + 'volcengine-plan': '/icons/providers/volcengine.svg', + 'xiaomi-mimo': '/icons/providers/xiaomimimo.svg', + 'hunyuan-3d': '/icons/providers/hunyuan-color.svg', + 'opencode': '/icons/providers/opencode.svg', + 'siliconflow-cn': '/icons/providers/siliconcloud.svg', + 'siliconflow-intl': '/icons/providers/siliconcloud.svg', + 'openai-chatgpt': '/icons/providers/openai.svg', + 'anthropic-claude-code': '/icons/providers/anthropic.svg', +} + +export function getProviderIcon(providerId: string): string { + return providerIconMap[providerId] || '/icons/providers/default.svg' +} + +// Hide the when the brand icon fails to load so the UI falls back cleanly. +export function onProviderIconError(e: Event) { + const img = e.target as HTMLImageElement + img.style.display = 'none' +} diff --git a/mateclaw-ui/src/views/Dashboard.vue b/mateclaw-ui/src/views/Dashboard.vue index 600b4c0b..d6e10112 100644 --- a/mateclaw-ui/src/views/Dashboard.vue +++ b/mateclaw-ui/src/views/Dashboard.vue @@ -55,6 +55,59 @@ +
+
+

{{ t('dashboard.models.title') }}

+

{{ t('dashboard.models.subtitle') }}

+
+
+
+
+ {{ t('dashboard.models.activeModel') }} + + + {{ activeProviderLabel }} · {{ activeModel.model }} + + + {{ t('dashboard.models.notSet') }} + +
+
+ + {{ readyProviderCount }}/{{ modelProviders.length }} {{ t('dashboard.models.configured') }} + + +
+
+
+ +
+
+ {{ t('dashboard.models.empty') }} + +
+
+
+

{{ t('dashboard.trend.title', '7-Day Trend') }}

@@ -133,10 +186,12 @@