11<script setup lang="ts">
2- import { ref , computed , onMounted , onUnmounted , defineAsyncComponent } from ' vue'
2+ import { ref , computed , onMounted , onUnmounted , defineAsyncComponent , watch } from ' vue'
33import { useData , useRoute } from ' vitepress'
44import { useI18n } from ' vue-i18n'
55import endsWith from ' lodash/endsWith'
@@ -97,6 +97,7 @@ const avatarCloseTimer = ref<ReturnType<typeof setTimeout> | null>(null)
9797
9898const avatarMenuItems = computed (() => [
9999 { title: ' Dashboard' , href: ' /dashboard' },
100+ { title: ' Connect AI' , href: ' /connect' },
100101 { title: ' Log out' , href: ' /log-out' },
101102])
102103
@@ -123,31 +124,109 @@ function openSearch() {
123124 )
124125}
125126
127+ // Helora 事件订阅的清理函数集(boot 之后由 on() 返回)
128+ const heloraDisposers: Array <() => void > = []
129+ let heloraReady = false
130+
131+ function syncHeloraTheme(dark : boolean ) {
132+ if (! heloraReady ) return
133+ console .log (7777777 , dark )
134+ window .Helora ?.setTheme ?.(dark ? ' dark' : ' light' )
135+ }
136+
137+ function syncHeloraLocale(locale : string ) {
138+ if (! heloraReady ) return
139+ // Helora 暂未暴露 setLocale,重新 boot 即可让其拉新语种文案
140+ window .Helora ?.boot ?.({
141+ proxy: ! endsWith (location .hostname , ' .xyz' ) && ! import .meta .env .DEV ? ' prod' : ' staging' ,
142+ guest: true ,
143+ configPlatform: ' web' ,
144+ configKey: ' helora-agent-openapi' ,
145+ source: ' web_openapi' ,
146+ locale ,
147+ theme: isDark .value ? ' dark' : ' light' ,
148+ headerActions: [
149+ {
150+ id: ' issue' ,
151+ label: t (' helora.submitIssue' ),
152+ icon: ' alert-circle' ,
153+ intent: ' event' ,
154+ },
155+ ],
156+ })
157+ }
158+
126159onMounted (() => {
127160 initLoginState ()
128161 document .addEventListener (' click' , onAvatarClickOutside )
129162
130- if (! isCnDomain ) {
131- const swSrc = ' https://assets.lbkrs.com/h5hub/support-widget/support-widget-1.0.7.iife.js'
132- const isProd = ! endsWith (location .hostname , ' .xyz' ) && ! import .meta .env .DEV
133- window .SupportWidgetConfig = {
134- isLoggedIn : function () {
135- return isLogin .value
136- },
137- loginUrl: createLoginRedirectPath ({ sw_open: ' 1' }),
163+ // Helora 客服(接替旧的 support-widget)
164+ // dev/staging 用 .dev 包 + proxy=staging;线上用 release 包 + proxy=prod
165+ const isProd = ! endsWith (location .hostname , ' .xyz' ) && ! import .meta .env .DEV
166+ const heloraSrc = ' https://assets.lbkrs.com/h5hub/helora-embed/helora-embed-1.0.0.dev.iife.js'
167+
168+ const bootHelora = () => {
169+ const Helora = window .Helora
170+ if (! Helora ) return
171+ Helora .boot ({
138172 proxy: isProd ? ' prod' : ' staging' ,
139- }
140- if (! document .querySelector (` script[src="${swSrc }"] ` )) {
141- const script = document .createElement (' script' )
142- script .src = swSrc
143- script .async = true
144- document .head .appendChild (script )
145- }
173+ guest: true ,
174+ configPlatform: ' web' ,
175+ configKey: ' helora-agent-openapi' ,
176+ source: ' web_openapi' ,
177+ locale: currentLocale .value ,
178+ theme: isDark .value ? ' dark' : ' light' ,
179+ headerActions: [
180+ {
181+ id: ' issue' ,
182+ label: t (' helora.submitIssue' ),
183+ icon: ' alert-circle' ,
184+ intent: ' event' ,
185+ },
186+ ],
187+ })
188+ heloraReady = true
189+
190+ // 订阅 header action(提交问题按钮)—— headerActions 里 intent: 'event' 会通过事件回调通知宿主
191+ const offAction = Helora .on ?.(' headerAction' , (payload : { id? : string }) => {
192+ if (payload ?.id === ' issue' ) {
193+ window .open (' https://github.com/longbridge/openapi/issues/new' , ' _blank' , ' noopener,noreferrer' )
194+ }
195+ })
196+ if (typeof offAction === ' function' ) heloraDisposers .push (offAction )
197+ }
198+
199+ if (! document .querySelector (` script[src="${heloraSrc }"] ` )) {
200+ const script = document .createElement (' script' )
201+ script .src = heloraSrc
202+ script .async = true
203+ script .onload = bootHelora
204+ document .head .appendChild (script )
205+ } else if (window .Helora ) {
206+ bootHelora ()
146207 }
208+
209+ // 主题切换 → 通知 Helora
210+ watch (isDark , (dark ) => syncHeloraTheme (dark ))
211+
212+ // 语言切换 → 通知 Helora
213+ // 当前 switchLocale 走 location.href(整页刷新),下次 mount 直接以新 locale boot;
214+ // 但 SPA 内若有路由级切换(不刷新),仍能命中这里
215+ watch (currentLocale , (locale , prev ) => {
216+ if (locale && locale !== prev ) syncHeloraLocale (locale )
217+ })
147218})
148219onUnmounted (() => {
149220 document .removeEventListener (' click' , onAvatarClickOutside )
150221 if (avatarCloseTimer .value ) clearTimeout (avatarCloseTimer .value )
222+ heloraDisposers .splice (0 ).forEach ((dispose ) => {
223+ try {
224+ dispose ()
225+ } catch {
226+ // ignore
227+ }
228+ })
229+ heloraReady = false
151230})
152231 </script >
153232
0 commit comments