From e10dd9d0a06a649cbdc5d25f6d9fb663915a0778 Mon Sep 17 00:00:00 2001 From: matevip Date: Fri, 15 May 2026 10:19:24 +0800 Subject: [PATCH] refactor(ui): swap ElMessage for project-native mcToast, finish mcConfirm migration --- .../src/components/ChangePasswordDialog.vue | 10 +- .../components/channels/ChannelEditModal.vue | 10 +- .../channels/ChannelOnboardingWizard.vue | 6 +- .../src/components/chat/MessageBubble.vue | 6 +- mateclaw-ui/src/components/chat/TalkMode.vue | 14 +- mateclaw-ui/src/components/common/McToast.vue | 138 ++++++++++++++++++ .../src/components/skill/ImportHubDialog.vue | 20 +-- .../skill/PreflightInstallDialog.vue | 8 +- .../components/skill/SkillSecretsPanel.vue | 28 ++-- .../workflow/GenerateWorkflowDialog.vue | 4 +- .../channels/useDingTalkAppRegister.ts | 12 +- .../channels/useFeishuAppRegister.ts | 14 +- .../composables/channels/useWecomBotAuth.ts | 14 +- .../channels/useWeixinQrcodePoll.ts | 10 +- mateclaw-ui/src/composables/useMcToast.ts | 128 ++++++++++++++++ mateclaw-ui/src/composables/useMcpServers.ts | 22 +-- mateclaw-ui/src/views/AcpEndpoints.vue | 12 +- mateclaw-ui/src/views/AgentContext.vue | 24 +-- mateclaw-ui/src/views/Agents.vue | 20 +-- mateclaw-ui/src/views/Backstage.vue | 20 +-- mateclaw-ui/src/views/Channels.vue | 10 +- mateclaw-ui/src/views/ChatConsole.vue | 73 ++++++--- mateclaw-ui/src/views/CronJobs.vue | 20 +-- mateclaw-ui/src/views/Datasources.vue | 20 +-- .../src/views/Memory/components/FactList.vue | 14 +- .../views/Memory/components/MemoryBrowser.vue | 6 +- mateclaw-ui/src/views/Memory/index.vue | 6 +- mateclaw-ui/src/views/Plugins.vue | 10 +- .../src/views/Security/Members/index.vue | 16 +- .../src/views/Security/ToolGuard/index.vue | 12 +- .../src/views/Security/Workspaces/index.vue | 12 +- mateclaw-ui/src/views/Sessions.vue | 6 +- .../src/views/Settings/FeatureFlags/index.vue | 7 +- .../Settings/Models/AddProviderDrawer.vue | 4 +- .../composables/useProviderDiscovery.ts | 6 +- .../composables/useProviderEnablement.ts | 8 +- .../Models/composables/useProviderForm.ts | 4 +- .../Models/composables/useProviderOAuth.ts | 28 ++-- .../Models/composables/useProviderPool.ts | 8 +- .../src/views/Settings/Models/index.vue | 14 +- .../Models/modals/DeviceCodeDialog.vue | 4 +- mateclaw-ui/src/views/SkillMarket.vue | 28 ++-- mateclaw-ui/src/views/SkillTemplates.vue | 4 +- mateclaw-ui/src/views/TokenUsage.vue | 4 +- mateclaw-ui/src/views/Tools.vue | 8 +- mateclaw-ui/src/views/Triggers.vue | 8 +- .../views/Wiki/components/HotCachePanel.vue | 11 +- .../Wiki/components/RawMaterialPanel.vue | 6 +- .../Wiki/components/TransformationsPanel.vue | 29 ++-- mateclaw-ui/src/views/Workflows.vue | 18 +-- 50 files changed, 609 insertions(+), 315 deletions(-) create mode 100644 mateclaw-ui/src/components/common/McToast.vue create mode 100644 mateclaw-ui/src/composables/useMcToast.ts diff --git a/mateclaw-ui/src/components/ChangePasswordDialog.vue b/mateclaw-ui/src/components/ChangePasswordDialog.vue index 7895e95c..ffc9caa1 100644 --- a/mateclaw-ui/src/components/ChangePasswordDialog.vue +++ b/mateclaw-ui/src/components/ChangePasswordDialog.vue @@ -70,7 +70,7 @@ + + diff --git a/mateclaw-ui/src/components/skill/ImportHubDialog.vue b/mateclaw-ui/src/components/skill/ImportHubDialog.vue index 5043a24f..846a2c53 100644 --- a/mateclaw-ui/src/components/skill/ImportHubDialog.vue +++ b/mateclaw-ui/src/components/skill/ImportHubDialog.vue @@ -149,7 +149,7 @@ diff --git a/mateclaw-ui/src/views/Backstage.vue b/mateclaw-ui/src/views/Backstage.vue index 3a7f96a1..78a0662d 100644 --- a/mateclaw-ui/src/views/Backstage.vue +++ b/mateclaw-ui/src/views/Backstage.vue @@ -172,7 +172,7 @@ diff --git a/mateclaw-ui/src/views/CronJobs.vue b/mateclaw-ui/src/views/CronJobs.vue index 7c910dfd..b9b25553 100644 --- a/mateclaw-ui/src/views/CronJobs.vue +++ b/mateclaw-ui/src/views/CronJobs.vue @@ -324,7 +324,7 @@ diff --git a/mateclaw-ui/src/views/Memory/components/FactList.vue b/mateclaw-ui/src/views/Memory/components/FactList.vue index 9570eae7..08b09918 100644 --- a/mateclaw-ui/src/views/Memory/components/FactList.vue +++ b/mateclaw-ui/src/views/Memory/components/FactList.vue @@ -71,7 +71,7 @@ diff --git a/mateclaw-ui/src/views/Memory/components/MemoryBrowser.vue b/mateclaw-ui/src/views/Memory/components/MemoryBrowser.vue index 498e36ce..5e5c7c6b 100644 --- a/mateclaw-ui/src/views/Memory/components/MemoryBrowser.vue +++ b/mateclaw-ui/src/views/Memory/components/MemoryBrowser.vue @@ -63,7 +63,7 @@ diff --git a/mateclaw-ui/src/views/Settings/Models/composables/useProviderDiscovery.ts b/mateclaw-ui/src/views/Settings/Models/composables/useProviderDiscovery.ts index 9490e8cf..695953b2 100644 --- a/mateclaw-ui/src/views/Settings/Models/composables/useProviderDiscovery.ts +++ b/mateclaw-ui/src/views/Settings/Models/composables/useProviderDiscovery.ts @@ -1,6 +1,6 @@ import { computed, reactive, ref, type Ref } from 'vue' import { useI18n } from 'vue-i18n' -import { ElMessage } from 'element-plus' +import { mcToast } from '@/composables/useMcToast' import { modelApi } from '@/api' import type { DiscoverResult, ProviderInfo, ProviderModelInfo, TestResult } from '@/types' @@ -98,7 +98,7 @@ export function useProviderDiscovery(deps: ListDeps) { selectedNewModelIds.value = res.data.newModels.map((m: ProviderModelInfo) => m.id) } } catch (error) { - ElMessage.error(error instanceof Error ? error.message : String(error)) + mcToast.error(error instanceof Error ? error.message : String(error)) } finally { discovering.value = false } @@ -116,7 +116,7 @@ export function useProviderDiscovery(deps: ListDeps) { await deps.refreshCurrentProvider(deps.currentProvider.value.id) return added } catch (error) { - ElMessage.error(error instanceof Error ? error.message : String(error)) + mcToast.error(error instanceof Error ? error.message : String(error)) return 0 } finally { applyingModels.value = false diff --git a/mateclaw-ui/src/views/Settings/Models/composables/useProviderEnablement.ts b/mateclaw-ui/src/views/Settings/Models/composables/useProviderEnablement.ts index 27482ec6..97b7bcc2 100644 --- a/mateclaw-ui/src/views/Settings/Models/composables/useProviderEnablement.ts +++ b/mateclaw-ui/src/views/Settings/Models/composables/useProviderEnablement.ts @@ -1,6 +1,6 @@ import { ref, type Ref } from 'vue' import { useI18n } from 'vue-i18n' -import { ElMessage } from 'element-plus' +import { mcToast } from '@/composables/useMcToast' import { modelApi } from '@/api' import type { EnableResult, ProviderInfo } from '@/types' @@ -55,7 +55,7 @@ export function useProviderEnablement(deps: ListDeps) { await Promise.all([loadCatalog(), deps.loadProviders()]) return res.data as EnableResult } catch (err) { - ElMessage.error(err instanceof Error ? err.message : String(err)) + mcToast.error(err instanceof Error ? err.message : String(err)) return null } finally { togglingId.value = null @@ -72,14 +72,14 @@ export function useProviderEnablement(deps: ListDeps) { // RFC-074 §2: silent switch + toast. Show the toast here so every caller // (drawer disable, card more-menu, etc.) gets consistent UX. if (result?.defaultSwitched) { - ElMessage.success(t('settings.model.defaultSwitchedToast', { + mcToast.success(t('settings.model.defaultSwitchedToast', { provider: result.newDefaultProviderId, model: result.newDefaultModel, })) } return result } catch (err) { - ElMessage.error(err instanceof Error ? err.message : String(err)) + mcToast.error(err instanceof Error ? err.message : String(err)) return null } finally { togglingId.value = null diff --git a/mateclaw-ui/src/views/Settings/Models/composables/useProviderForm.ts b/mateclaw-ui/src/views/Settings/Models/composables/useProviderForm.ts index 5e50c050..3a9e9780 100644 --- a/mateclaw-ui/src/views/Settings/Models/composables/useProviderForm.ts +++ b/mateclaw-ui/src/views/Settings/Models/composables/useProviderForm.ts @@ -1,6 +1,6 @@ import { computed, reactive, ref } from 'vue' import { useI18n } from 'vue-i18n' -import { ElMessage } from 'element-plus' +import { mcToast } from '@/composables/useMcToast' import { mcConfirm } from '@/components/common/useConfirm' import { modelApi } from '@/api' import type { ProviderInfo } from '@/types' @@ -159,7 +159,7 @@ export function useProviderForm(deps: ListDeps) { if (!editingProvider.value) { const id = providerForm.id.trim() if (!id || !PROVIDER_ID_PATTERN.test(id)) { - ElMessage.error(t('settings.model.providerIdInvalid')) + mcToast.error(t('settings.model.providerIdInvalid')) return false } providerForm.id = id diff --git a/mateclaw-ui/src/views/Settings/Models/composables/useProviderOAuth.ts b/mateclaw-ui/src/views/Settings/Models/composables/useProviderOAuth.ts index 99244cc4..f6f6c9ff 100644 --- a/mateclaw-ui/src/views/Settings/Models/composables/useProviderOAuth.ts +++ b/mateclaw-ui/src/views/Settings/Models/composables/useProviderOAuth.ts @@ -1,6 +1,6 @@ import { ref, type Ref } from 'vue' import { useI18n } from 'vue-i18n' -import { ElMessage } from 'element-plus' +import { mcToast } from '@/composables/useMcToast' import { claudeCodeOAuthApi, oauthApi } from '@/api' import type { ProviderInfo } from '@/types' @@ -74,12 +74,12 @@ export function useProviderOAuth(deps: FormDeps & ListDeps) { try { start = await oauthApi.deviceStart() } catch (e: any) { - ElMessage.error(e.msg || 'Device code request failed') + mcToast.error(e.msg || 'Device code request failed') return } const data = start.data if (!data?.deviceAuthId || !data?.userCode) { - ElMessage.error('Device code response was incomplete') + mcToast.error('Device code response was incomplete') return } @@ -100,7 +100,7 @@ export function useProviderOAuth(deps: FormDeps & ListDeps) { return } if (Date.now() > deviceCodeDialog.value.expiresAt) { - ElMessage.warning(t('settings.model.oauthDeviceExpired')) + mcToast.warning(t('settings.model.oauthDeviceExpired')) closeDeviceCodeDialog() return } @@ -111,12 +111,12 @@ export function useProviderOAuth(deps: FormDeps & ListDeps) { activeDeviceAuthId = null stopDevicePolling() deviceCodeDialog.value.visible = false - ElMessage.success(t('settings.model.oauthLoginSuccess')) + mcToast.success(t('settings.model.oauthLoginSuccess')) await reloadProvidersAndSync() return } if (status === 'EXPIRED') { - ElMessage.warning(t('settings.model.oauthDeviceExpired')) + mcToast.warning(t('settings.model.oauthDeviceExpired')) closeDeviceCodeDialog() return } @@ -131,13 +131,13 @@ export function useProviderOAuth(deps: FormDeps & ListDeps) { try { const res: any = await claudeCodeOAuthApi.reload() if (res.data?.connected && !res.data?.expired) { - ElMessage.success(t('settings.model.oauthLoginSuccess')) + mcToast.success(t('settings.model.oauthLoginSuccess')) } else { - ElMessage.warning(t('settings.model.claudeCodeOauthInstructions')) + mcToast.warning(t('settings.model.claudeCodeOauthInstructions')) } await reloadProvidersAndSync() } catch (e: any) { - ElMessage.error(e.msg || 'Claude Code OAuth detection failed') + mcToast.error(e.msg || 'Claude Code OAuth detection failed') } return } @@ -160,14 +160,14 @@ export function useProviderOAuth(deps: FormDeps & ListDeps) { if (statusRes.data?.connected) { clearInterval(pollInterval) if (authWindow && !authWindow.closed) authWindow.close() - ElMessage.success(t('settings.model.oauthLoginSuccess')) + mcToast.success(t('settings.model.oauthLoginSuccess')) await reloadProvidersAndSync() } } catch { /* ignore polling errors */ } }, 2000) setTimeout(() => clearInterval(pollInterval), 30000) } catch (e: any) { - ElMessage.error(e.msg || 'OAuth login failed') + mcToast.error(e.msg || 'OAuth login failed') } } @@ -176,15 +176,15 @@ export function useProviderOAuth(deps: FormDeps & ListDeps) { // Code app, not MateClaw — direct the user to log out there instead of // clobbering their machine-level login. if (providerId === 'anthropic-claude-code') { - ElMessage.info(t('settings.model.claudeCodeOauthRevokeHint')) + mcToast.info(t('settings.model.claudeCodeOauthRevokeHint')) return } try { await oauthApi.revoke() - ElMessage.success(t('settings.model.oauthRevokeSuccess')) + mcToast.success(t('settings.model.oauthRevokeSuccess')) await reloadProvidersAndSync() } catch (e: any) { - ElMessage.error(e.msg || 'OAuth revoke failed') + mcToast.error(e.msg || 'OAuth revoke failed') } } diff --git a/mateclaw-ui/src/views/Settings/Models/composables/useProviderPool.ts b/mateclaw-ui/src/views/Settings/Models/composables/useProviderPool.ts index f8d05004..2fd3ad1b 100644 --- a/mateclaw-ui/src/views/Settings/Models/composables/useProviderPool.ts +++ b/mateclaw-ui/src/views/Settings/Models/composables/useProviderPool.ts @@ -1,6 +1,6 @@ import { ref } from 'vue' import { useI18n } from 'vue-i18n' -import { ElMessage } from 'element-plus' +import { mcToast } from '@/composables/useMcToast' import { providerPoolApi } from '@/api' import type { ProviderInfo } from '@/types' @@ -29,13 +29,13 @@ export function useProviderPool(deps: ListDeps) { // refreshes everything the UI needs (badge + status pill + dropdown filter). await deps.loadProviders() if (data.success) { - ElMessage.success(t('settings.model.poolReprobeOk')) + mcToast.success(t('settings.model.poolReprobeOk')) } else { - ElMessage.warning(t('settings.model.poolReprobeFail', { error: data.errorMessage || '—' })) + mcToast.warning(t('settings.model.poolReprobeFail', { error: data.errorMessage || '—' })) } return data } catch (err) { - ElMessage.error(t('settings.model.poolReprobeFail', { + mcToast.error(t('settings.model.poolReprobeFail', { error: err instanceof Error ? err.message : String(err) })) } finally { diff --git a/mateclaw-ui/src/views/Settings/Models/index.vue b/mateclaw-ui/src/views/Settings/Models/index.vue index c16bc397..967610ce 100644 --- a/mateclaw-ui/src/views/Settings/Models/index.vue +++ b/mateclaw-ui/src/views/Settings/Models/index.vue @@ -191,7 +191,7 @@ diff --git a/mateclaw-ui/src/views/SkillMarket.vue b/mateclaw-ui/src/views/SkillMarket.vue index d64ae729..078c10d9 100644 --- a/mateclaw-ui/src/views/SkillMarket.vue +++ b/mateclaw-ui/src/views/SkillMarket.vue @@ -654,7 +654,7 @@ diff --git a/mateclaw-ui/src/views/Triggers.vue b/mateclaw-ui/src/views/Triggers.vue index cb4cca56..c7f6d863 100644 --- a/mateclaw-ui/src/views/Triggers.vue +++ b/mateclaw-ui/src/views/Triggers.vue @@ -171,7 +171,7 @@