From 22894ac4b1dcc57796873db628c7a65f3a90c323 Mon Sep 17 00:00:00 2001 From: matevip Date: Tue, 28 Apr 2026 11:08:36 +0800 Subject: [PATCH] perf(channels): split Channels.vue, lazy-load modal, async locales, keep-alive route - Extract create/edit modal into ChannelEditModal.vue (defineAsyncComponent), shrinking Channels.vue from 1438 to 370 lines and dropping ~30KB from the initial route chunk. - Move side-effect logic into composables: useWeixinQrcodePoll (QR + 2s status poll, auto-cleanup) and useWecomBotAuth (lazy SDK script with module-level promise dedupe). Pure config-JSON helpers move to utils/channelConfigJson.ts. - Switch i18n locales from static imports to dynamic import keyed by current locale; applyLocale becomes async to avoid first-render flicker. - /channels route opts into keep-alive (meta.keepAlive=true). Channels.vue pauses status polling in onDeactivated and resumes in onActivated, with an isActive guard to prevent late-resolving timers from leaking after navigation. - Initial load goes from serial 3-RTT to Promise.all + 4-card el-skeleton. --- .../components/channels/ChannelEditModal.vue | 748 ++++++++++ .../composables/channels/useWecomBotAuth.ts | 87 ++ .../channels/useWeixinQrcodePoll.ts | 107 ++ mateclaw-ui/src/i18n/index.ts | 34 +- mateclaw-ui/src/router/index.ts | 5 +- mateclaw-ui/src/utils/channelConfigJson.ts | 101 ++ mateclaw-ui/src/views/Channels.vue | 1327 ++--------------- mateclaw-ui/src/views/layout/MainLayout.vue | 9 +- 8 files changed, 1233 insertions(+), 1185 deletions(-) create mode 100644 mateclaw-ui/src/components/channels/ChannelEditModal.vue create mode 100644 mateclaw-ui/src/composables/channels/useWecomBotAuth.ts create mode 100644 mateclaw-ui/src/composables/channels/useWeixinQrcodePoll.ts create mode 100644 mateclaw-ui/src/utils/channelConfigJson.ts diff --git a/mateclaw-ui/src/components/channels/ChannelEditModal.vue b/mateclaw-ui/src/components/channels/ChannelEditModal.vue new file mode 100644 index 00000000..bc334185 --- /dev/null +++ b/mateclaw-ui/src/components/channels/ChannelEditModal.vue @@ -0,0 +1,748 @@ + + + + + diff --git a/mateclaw-ui/src/composables/channels/useWecomBotAuth.ts b/mateclaw-ui/src/composables/channels/useWecomBotAuth.ts new file mode 100644 index 00000000..48896dbb --- /dev/null +++ b/mateclaw-ui/src/composables/channels/useWecomBotAuth.ts @@ -0,0 +1,87 @@ +import { ref } from 'vue' +import { useI18n } from 'vue-i18n' +import { ElMessage } from 'element-plus' + +const SDK_URL = 'https://wwcdn.weixin.qq.com/node/wework/js/wecom-aibot-sdk@0.1.0.min.js' +const SOURCE = 'mateclaw' + +// Module-level guard: the SDK script tag is appended to exactly once +// across all component instances and re-renders. +let sdkLoadPromise: Promise | null = null + +function loadSDK(): Promise { + if ((window as any).WecomAIBotSDK) return Promise.resolve() + if (sdkLoadPromise) return sdkLoadPromise + sdkLoadPromise = new Promise((resolve, reject) => { + const script = document.createElement('script') + script.src = SDK_URL + script.async = true + script.onload = () => resolve() + script.onerror = () => { + sdkLoadPromise = null // allow retry on next call + reject(new Error('WeCom SDK load failed')) + } + document.body.appendChild(script) + }) + return sdkLoadPromise +} + +export interface WecomBotAuthResult { + botid: string + secret: string +} + +/** + * 企业微信扫码授权:动态加载官方 JS SDK,弹出授权窗口,回调 botid/secret。 + * + * 拆出来的好处: + * - SDK 脚本只在用户真点"授权"按钮时才注入,不污染每个页面的 + * - 多次点击不会重复 append