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