252 lines
6.8 KiB
TypeScript
252 lines
6.8 KiB
TypeScript
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<UserStore>((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 || '登录失败');
|
||
}
|
||
},
|
||
}));
|