import { query, queryLogin } from '@/modules/query'; import { TencentCaptcha } from '@/wx/tencent-captcha.ts'; import { message } from '@/modules/message'; import { create } from 'zustand'; export type Config = { loginWay: any[]; wxLogin: { appid: string; redirect_uri: string; }; wxmpLogin: { loginUrl?: string; // 微信公众号的网页授权登陆 appid?: string; // 微信公众号的appid redirect_uri?: string; // 微信公众号的网页授权登陆 }; captchaAppId: string; loginSuccess: string; loginSuccessIsNew: string; logo: string; logoStyle: { borderRadius: string; width?: string; height?: string; }; beian: string; }; export const inIframeToDo = async (config?: Config) => { const isInIframe = window !== window.parent && !window.opener; if (isInIframe && config) { try { // 检查是否同源 const isSameOrigin = (() => { try { // 尝试访问父窗口的 location.origin,如果能访问则是同源 return window.parent.location.origin === window.location.origin; } catch (e) { // 如果出现跨域错误,则不是同源 return false; } })(); const isLocalhost = window.location.hostname === 'localhost'; const isKevisual = window.location.hostname.includes('kevisual'); if (isSameOrigin || isLocalhost || isKevisual) { // 同源情况下,可以直接向父窗口传递配置 window.parent.postMessage( { type: 'kevisual-login', data: config, }, window.location.origin, ); console.log('已向父窗口传递登录配置信息'); } } catch (error) { console.error('向父窗口传递配置信息失败:', error); } } return isInIframe; }; export const redirectToSuccess = async (config: Config) => { const href = location.href; const url = new URL(href); const check = await inIframeToDo(config); if (check) { return; } const redirect = url.searchParams.get('redirect'); if (redirect) { const href = decodeURIComponent(redirect); window.open(href, '_self'); } await new Promise((resolve) => { setTimeout(() => { resolve(true); }, 1000); }); if (config?.loginSuccess) { location.href = config?.loginSuccess; } else { location.href = '/'; } }; type UserStore = { isAuthenticated: boolean; qrCodeUrl: string; checkAuthStatus: () => void; getCode: (phone: string, captcha: TencentCaptcha) => void; /** * 手机号登录 * @param phone 手机号 * @param code 验证码 */ login: (phone: string, code: string) => void; updateUser: (data: any, opts?: { needRedirect?: boolean }) => void; getUpdateUser: () => void; data: any; setData: (data: any) => void; config: Config | null; setConfig: (config: any) => void; loadedConfig: boolean; setLoadedConfig: (loadedConfig: boolean) => void; /** * 账号密码登录 * @param username 账号 * @param password 密码 */ loginByAccount: (username: string, password: string) => void; /** * 检查是否需要跳转, 插件登陆 */ queryCheck: () => void; loginByWechat: (code: string) => void; }; export const useUserStore = create((set, get) => ({ isAuthenticated: false, qrCodeUrl: '', checkAuthStatus: () => { // }, getCode: async (phone, captcha) => { const res = await query.post({ path: 'sms', key: 'send', data: { phone, captcha, }, }); if (res.code === 200) { // do something message.success('验证码发送成功'); } else { message.error(res.message || '验证码发送失败'); } }, login: async (phone, code) => { const config = get().config!; const res = await query.post({ path: 'sms', key: 'login', data: { phone, code, }, }); if (res.code === 200) { message.success('登录成功'); set({ isAuthenticated: true }); redirectToSuccess(config); } else { message.error(res.message || '登录失败'); } }, updateUser: async (data, opts) => { const config = get().config!; const res = await query.post({ path: 'user', key: 'updateInfo', data, }); if (res.code === 200) { message.success('更新成功'); if (opts?.needRedirect) { setTimeout(() => { location.href = config?.loginSuccess; }, 1000); } } else { message.error(res.message || '更新失败'); } }, getUpdateUser: async () => { const res = await query.post({ path: 'user', key: 'getUpdateInfo', }); if (res.code === 200) { set({ data: res.data }); } else { message.error(res.message || '获取用户信息失败'); } }, data: {}, setData: (data) => set({ data }), loadedConfig: false, setLoadedConfig: (loadedConfig) => set({ loadedConfig }), config: null, setConfig: (config) => set({ config, loadedConfig: true }), loginByAccount: async (username, password) => { const config = get().config!; const isEmail = username.includes('@'); const data: any = { password }; if (isEmail) { data.email = username; } else { data.username = username; } const res = await queryLogin.login(data); if (res.code === 200) { message.success('登录成功'); set({ isAuthenticated: true }); redirectToSuccess(config); } else { message.error(res.message || '登录失败'); } }, queryCheck: async () => { // const const userCheck = 'user-check'; const url = new URL(location.href); const redirect = url.searchParams.get('redirect'); const redirectUrl = redirect ? decodeURIComponent(redirect) : ''; const checkKey = url.searchParams.get(userCheck); if (redirect && checkKey) { // 通过refresh_token 刷新token const me = await queryLogin.getMe(); if (me.code === 200) { message.success('登录插件中...'); const token = await queryLogin.cacheStore.getAccessToken(); const newRedirectUrl = new URL(redirectUrl); newRedirectUrl.searchParams.set('token', token + ''); setTimeout(() => { window.open(newRedirectUrl.toString(), '_blank'); }, 2000); return; } // 刷新token失败,登陆页自己跳转 } console.log('checkKey', checkKey, redirectUrl); }, loginByWechat: async (code) => { const config = get().config!; if (!code) { message.error('code is required'); return; } const res = await queryLogin.loginByWechat({ code }); if (res.code === 200) { message.success('登录成功'); redirectToSuccess(config); } else { message.error(res.message || '登录失败'); } }, }));