Skip to content

Commit 1ede617

Browse files
committed
feat: enhance WeCom QR code login with iframe creation and improved language handling
1 parent 5329b44 commit 1ede617

File tree

1 file changed

+101
-60
lines changed

1 file changed

+101
-60
lines changed

ui/src/views/chat/user-login/scanCompinents/wecomQrCode.vue

Lines changed: 101 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -3,85 +3,126 @@
33
</template>
44

55
<script lang="ts" setup>
6-
import { useRoute, useRouter } from 'vue-router'
7-
import * as ww from '@wecom/jssdk'
8-
import {
9-
WWLoginLangType,
10-
WWLoginPanelSizeType,
11-
WWLoginRedirectType,
12-
WWLoginType,
13-
} from '@wecom/jssdk'
14-
import { ref, nextTick } from 'vue'
15-
import { MsgError } from '@/utils/message'
6+
import {nextTick, defineProps, onBeforeUnmount} from 'vue'
7+
import {useRoute, useRouter} from 'vue-router'
8+
import {getBrowserLang} from '@/locales'
169
import useStore from '@/stores'
17-
import { getBrowserLang } from '@/locales'
18-
19-
const router = useRouter()
20-
const route = useRoute()
21-
const {
22-
params: { accessToken },
23-
} = route as any
24-
const wwLogin = ref({})
25-
const obj = ref<any>({ isWeComLogin: false })
26-
const { chatUser } = useStore()
27-
10+
const WE_COM_ORIGIN = 'https://login.work.weixin.qq.com'
11+
const LOGIN_SUCCESS_EVENT = 'onLoginSuccess'
12+
const LOGIN_STATE = 'fit2cloud-wecom-qr'
2813
const props = defineProps<{
2914
config: {
30-
callback_url: string
3115
app_secret: string
3216
app_key: string
3317
corp_id?: string
3418
agent_id?: string
19+
callback_url: string
3520
}
3621
}>()
3722
38-
const init = async () => {
39-
await nextTick() // 确保DOM已更新
40-
const data = {
41-
corpId: props.config.corp_id,
42-
agentId: props.config.agent_id,
43-
}
44-
const lang = localStorage.getItem('MaxKB-locale') || getBrowserLang() || 'en-US'
45-
const redirectUri = props.config.callback_url
23+
const router = useRouter()
24+
const route = useRoute()
25+
const {chatUser} = useStore()
26+
27+
const {
28+
params: {accessToken},
29+
} = route as any
30+
31+
let iframe: HTMLIFrameElement | null = null
32+
33+
function createTransparentIFrame(el: string) {
34+
const container = document.querySelector(el)
35+
if (!container) return null
36+
37+
const iframeEl = document.createElement('iframe')
38+
iframeEl.style.cssText = `
39+
display: block;
40+
border: none;
41+
background: transparent;
42+
`
43+
iframeEl.referrerPolicy = 'origin'
44+
iframeEl.setAttribute('frameborder', '0')
45+
iframeEl.setAttribute('allowtransparency', 'true')
46+
47+
container.appendChild(iframeEl)
48+
return iframeEl
49+
}
50+
51+
function getLang() {
52+
const lang = localStorage.getItem('MaxKB-locale') || getBrowserLang()
53+
return lang === 'en-US' ? 'en' : 'zh'
54+
}
55+
56+
function safeParse(data: unknown) {
4657
try {
47-
wwLogin.value = ww.createWWLoginPanel({
48-
el: '#wecom-qr',
49-
params: {
50-
login_type: WWLoginType.corpApp,
51-
appid: data.corpId || '',
52-
agentid: data.agentId,
53-
redirect_uri: redirectUri,
54-
state: 'fit2cloud-wecom-qr',
55-
lang: lang === 'zh-CN' || lang === 'zh-Hant' ? WWLoginLangType.zh : WWLoginLangType.en,
56-
redirect_type: WWLoginRedirectType.callback,
57-
panel_size: WWLoginPanelSizeType.small,
58-
},
59-
onCheckWeComLogin: obj.value,
60-
async onLoginSuccess({ code }: any) {
61-
chatUser.wecomCallback(code, accessToken).then(() => {
62-
setTimeout(() => {
63-
router.push({
64-
name: 'chat',
65-
params: { accessToken: accessToken },
66-
query: route.query,
67-
})
68-
})
69-
})
70-
},
71-
onLoginFail(err) {
72-
MsgError(`${err.errMsg}`)
73-
},
74-
})
75-
} catch (error) {}
58+
return typeof data === 'string' ? JSON.parse(data) : data
59+
} catch {
60+
return null
61+
}
62+
}
63+
64+
async function handleLoginSuccess(code: string) {
65+
await chatUser.wecomCallback(code, accessToken)
66+
67+
router.push({
68+
name: 'chat',
69+
params: {accessToken},
70+
query: route.query,
71+
})
72+
}
73+
74+
function handleWindowMessage(event: MessageEvent) {
75+
if (event.origin !== WE_COM_ORIGIN) return
76+
77+
const payload: any = safeParse(event.data)
78+
if (!payload?.args) return
79+
80+
if (payload.args.name === LOGIN_SUCCESS_EVENT) {
81+
const code = payload.args?.data?.code
82+
if (!code) return
83+
84+
handleLoginSuccess(code)
85+
cleanup()
86+
}
7687
}
7788
89+
function cleanup() {
90+
window.removeEventListener('message', handleWindowMessage)
91+
iframe?.remove()
92+
iframe = null
93+
}
94+
95+
const init = async () => {
96+
await nextTick()
97+
98+
iframe = createTransparentIFrame('#wecom-qr')
99+
if (!iframe) return
100+
101+
const redirectUri = encodeURIComponent(props.config.callback_url)
102+
103+
iframe.src =
104+
`${WE_COM_ORIGIN}/wwlogin/sso/login` +
105+
`?login_type=CorpApp` +
106+
`&appid=${props.config.corp_id}` +
107+
`&agentid=${props.config.agent_id}` +
108+
`&redirect_uri=${redirectUri}` +
109+
`&state=${LOGIN_STATE}` +
110+
`&lang=${getLang()}` +
111+
`&panel_size=small` +
112+
`&redirect_type=callback`
113+
114+
window.addEventListener('message', handleWindowMessage)
115+
}
116+
117+
onBeforeUnmount(cleanup)
118+
78119
init()
79120
</script>
80121

81122
<style scoped lang="scss">
82123
#wecom-qr {
83124
margin-top: -20px;
84-
height: 331px;
125+
height: 360px;
85126
justify-content: center;
86127
}
87128
</style>

0 commit comments

Comments
 (0)