♻️ refactored login-related code

This commit is contained in:
2024-12-21 01:15:57 +08:00
parent 76336d1553
commit 59a8b63ee7
14 changed files with 139 additions and 128 deletions

View File

@@ -1,18 +0,0 @@
import {service} from "@/utils/alova/service.ts";
/**
* 获取Gitee登录链接
*/
export const getGiteeUrl = () => {
return service.Get('/api/oauth/gitee/url',
{
meta: {
ignoreToken: true,
},
cacheFor: {
mode: "restore",
expire: 1000 * 60 * 60 * 24
}
}
);
};

View File

@@ -1,21 +0,0 @@
import {service} from "@/utils/alova/service.ts";
/**
* Get Github OAuth URL
*/
export const getGithubUrl = (state: string) => {
return service.Get('/api/oauth/github/url',
{
params: {
state: state
},
meta: {
ignoreToken: true,
},
cacheFor: {
mode: "restore",
expire: 1000 * 60 * 60 * 24
}
}
);
};

57
src/api/oauth/index.ts Normal file
View File

@@ -0,0 +1,57 @@
import {service} from "@/utils/alova/service.ts";
/**
* 获取Gitee登录链接
*/
export const getGiteeUrl = () => {
return service.Get('/api/oauth/gitee/url',
{
meta: {
ignoreToken: true,
},
cacheFor: {
mode: "restore",
expire: 1000 * 60 * 60 * 24
}
}
);
};
/**
* Get Github OAuth URL
*/
export const getGithubUrl = (state: string) => {
return service.Get('/api/oauth/github/url',
{
params: {
state: state
},
meta: {
ignoreToken: true,
},
cacheFor: {
mode: "restore",
expire: 1000 * 60 * 60 * 24
}
}
);
};
export const getQQUrl = (state: string) => {
return service.Get('/api/oauth/qq/url',
{
params: {
state: state
},
meta: {
ignoreToken: true,
},
cacheFor: {
mode: "restore",
expire: 1000 * 60 * 60 * 24
}
}
);
};

View File

@@ -1,18 +0,0 @@
import {service} from "@/utils/alova/service.ts";
export const getQQUrl = (state: string) => {
return service.Get('/api/oauth/qq/url',
{
params: {
state: state
},
meta: {
ignoreToken: true,
},
cacheFor: {
mode: "restore",
expire: 1000 * 60 * 60 * 24
}
}
);
};

View File

@@ -1,20 +0,0 @@
import {service} from "@/utils/alova/service.ts";
/**
* 获取临时二维码
* @param clientId
*/
export const generateQrCode = (clientId: string) => {
return service.Get('/api/oauth/wechat/qrcode',
{
params: {
client_id: clientId
},
cacheFor: null,
meta: {
ignoreToken: true,
},
}
);
};

View File

@@ -1,5 +1,5 @@
import {service} from "@/utils/alova/service.ts"; import {service} from "@/utils/alova/service.ts";
import {AccountLogin, PhoneLogin, ResetPassword} from "@/types/user"; import {AccountLogin, PhoneLogin, ResetPassword, WechatOffiaccountLogin} from "@/types/user";
/** /**
* 刷新token * 刷新token
@@ -8,7 +8,7 @@ export const refreshToken = () => {
return service.Post('/api/auth/token/refresh', {}, { return service.Post('/api/auth/token/refresh', {}, {
meta: { meta: {
authRole: 'refreshToken', authRole: 'refreshToken',
ignoreToken: true, ignoreToken: false,
signature: true signature: true
} }
}); });
@@ -89,16 +89,14 @@ export const resetPasswordApi = (param: ResetPassword) => {
} }
); );
}; };
/** /**
* 获取用户设备信息 * 微信扫码登录
* @param access_token * @param param
*/ */
export const getUserDevice = (access_token: string) => { export const wechatOffiaccountLoginApi = (param: WechatOffiaccountLogin) => {
return service.Post('/api/user/device', return service.Post('/api/user/wechat/offiaccount/login', {
{ openid: param.openid,
access_token: access_token, client_id: param.client_id,
}, },
{ {
meta: { meta: {
@@ -108,3 +106,21 @@ export const getUserDevice = (access_token: string) => {
} }
); );
}; };
/**
* 获取临时二维码
* @param clientId
*/
export const generateQrCode = (clientId: string) => {
return service.Post('/api/user/wechat/offiaccount/qrcode', {
client_id: clientId
}, {
cacheFor: 60 * 60 * 24,
meta: {
ignoreToken: true,
signature: true
},
}
);
};

View File

@@ -29,7 +29,7 @@ const router: Router = createRouter({
router.beforeEach((to, _from, next) => { router.beforeEach((to, _from, next) => {
// start(); // start();
const user = useStore().user; const user = useStore().user;
const token: string | undefined = user.user.access_token; const token: string | undefined = user.token;
const userId: string | undefined = user.user.uid; const userId: string | undefined = user.user.uid;
// 检查用户是否已登录 // 检查用户是否已登录

View File

@@ -1,24 +1,20 @@
import {defineStore} from 'pinia'; import {defineStore} from 'pinia';
import {reactive} from 'vue';
import {generateClientId} from "@/api/client"; import {generateClientId} from "@/api/client";
import {getGithubUrl} from "@/api/oauth/github.ts";
import {getQQUrl} from "@/api/oauth/qq.ts";
import {getGiteeUrl} from "@/api/oauth/gitee.ts";
import {getUserDevice} from "@/api/user";
import {message} from "ant-design-vue"; import {message} from "ant-design-vue";
import {useI18n} from "vue-i18n"; import {useI18n} from "vue-i18n";
import {getGiteeUrl, getGithubUrl, getQQUrl} from "@/api/oauth";
export const useAuthStore = defineStore( export const useAuthStore = defineStore(
'user', 'user',
() => { () => {
const user: any = reactive({ const user: any = reactive({
access_token: '',
uid: '', uid: '',
username: '', username: '',
nickname: '', nickname: '',
avatar: '', avatar: '',
status: '', status: '',
}); });
const token: any = ref<string>('');
const clientId = ref<string>(''); const clientId = ref<string>('');
const githubRedirectUrl = ref<string>(''); const githubRedirectUrl = ref<string>('');
const giteeRedirectUrl = ref<string>(''); const giteeRedirectUrl = ref<string>('');
@@ -74,14 +70,13 @@ export const useAuthStore = defineStore(
if (typeof e.data === 'string') { if (typeof e.data === 'string') {
const res: any = JSON.parse(e.data); const res: any = JSON.parse(e.data);
if (res && res.code === 200) { if (res && res.code === 200) {
const {data} = res; const {uid, access_token, username, avatar, nickname, status} = res.data;
user.uid = data.uid; user.uid = uid;
user.access_token = data.access_token; user.username = username;
user.username = data.username; user.avatar = avatar;
user.avatar = data.avatar; user.nickname = nickname;
user.nickname = data.nickname; user.status = status;
user.status = data.status; token.value = access_token;
await getUserDevice(data.access_token);
message.success(t('login.loginSuccess')); message.success(t('login.loginSuccess'));
window.removeEventListener("message", messageHandler); window.removeEventListener("message", messageHandler);
setTimeout(() => { setTimeout(() => {
@@ -130,9 +125,19 @@ export const useAuthStore = defineStore(
window.addEventListener("message", messageHandler); window.addEventListener("message", messageHandler);
} }
function clear() {
token.value = "";
user.avatar = "";
user.uid = "";
user.username = "";
user.nickname = "";
user.status = "";
}
return { return {
user, user,
token,
clientId, clientId,
getGithubRedirectUrl, getGithubRedirectUrl,
getGiteeRedirectUrl, getGiteeRedirectUrl,
@@ -141,6 +146,7 @@ export const useAuthStore = defineStore(
openGithubUrl, openGithubUrl,
openGiteeUrl, openGiteeUrl,
openQQUrl, openQQUrl,
clear
}; };
}, },
{ {
@@ -154,7 +160,7 @@ export const useAuthStore = defineStore(
persist: true, persist: true,
storage: localStorage, storage: localStorage,
key: 'user', key: 'user',
includePaths: ['user', "clientId", "githubRedirectUrl", "giteeRedirectUrl", "qqRedirectUrl"] includePaths: ['user', 'token', "clientId"]
} }
} }
); );

5
src/types/user.d.ts vendored
View File

@@ -18,3 +18,8 @@ export interface ResetPassword {
password?: string; password?: string;
repassword?: string; repassword?: string;
} }
export interface WechatOffiaccountLogin {
openid:string;
client_id:string;
}

View File

@@ -28,7 +28,7 @@ const {onAuthRequired, onResponseRefreshToken} = createServerTokenAuthentication
const user = useStore().user; const user = useStore().user;
const res: any = await refreshToken(); const res: any = await refreshToken();
if (res && res.code === 200) { if (res && res.code === 200) {
user.user.access_token = res.data; user.token = res.data;
} }
} }
} }
@@ -46,7 +46,8 @@ export const service = createAlova({
beforeRequest: onAuthRequired(async (method: any) => { beforeRequest: onAuthRequired(async (method: any) => {
if (!method.meta?.ignoreToken) { if (!method.meta?.ignoreToken) {
const user = useStore().user; const user = useStore().user;
method.config.headers.Authorization = `${import.meta.env.VITE_APP_TOKEN_KEY} ${user.user.access_token}`; method.config.headers.Authorization = `${import.meta.env.VITE_APP_TOKEN_KEY} ${user.token}`;
method.config.headers['X-UID'] = user.user.uid;
} }
const lang = useStore().lang; const lang = useStore().lang;
method.config.headers['Accept-Language'] = lang.lang || 'zh'; method.config.headers['Accept-Language'] = lang.lang || 'zh';
@@ -72,11 +73,9 @@ export const service = createAlova({
}, 1000); }, 1000);
}, },
}); });
return Promise.reject(response.data); return Promise.reject();
} }
return response.data; return response.data;
}, },
onError: onError:
(error: AxiosError, _method: any) => { (error: AxiosError, _method: any) => {

View File

@@ -53,7 +53,7 @@ export class WebSocketService {
}; };
private handleMessage = (event: MessageEvent): void => { private handleMessage = (event: MessageEvent): void => {
const {data} = event; const data = JSON.parse(event.data);
if (this.callbacks.message) { if (this.callbacks.message) {
this.callbacks.message.forEach((cb) => (cb as MessageCallback)(data)); this.callbacks.message.forEach((cb) => (cb as MessageCallback)(data));
} }

View File

@@ -374,11 +374,11 @@ async function phoneLoginSubmit() {
const res: any = await phoneLoginApi(phoneLoginForm); const res: any = await phoneLoginApi(phoneLoginForm);
if (res && res.code === 200) { if (res && res.code === 200) {
userStore.user.uid = res.data.uid; userStore.user.uid = res.data.uid;
userStore.user.access_token = res.data.access_token;
userStore.user.username = res.data.username; userStore.user.username = res.data.username;
userStore.user.avatar = res.data.avatar; userStore.user.avatar = res.data.avatar;
userStore.user.nickname = res.data.nickname; userStore.user.nickname = res.data.nickname;
userStore.user.status = res.data.status; userStore.user.status = res.data.status;
userStore.token = res.data.access_token;
message.success(t('login.loginSuccess')); message.success(t('login.loginSuccess'));
loginLoading.value = false; loginLoading.value = false;
setTimeout(() => { setTimeout(() => {
@@ -461,11 +461,11 @@ async function checkAccountLoginCaptcha(angle: number) {
const res: any = await accountLoginApi(params); const res: any = await accountLoginApi(params);
if (res && res.code === 200) { if (res && res.code === 200) {
userStore.user.uid = res.data.uid; userStore.user.uid = res.data.uid;
userStore.user.access_token = res.data.access_token;
userStore.user.username = res.data.username; userStore.user.username = res.data.username;
userStore.user.avatar = res.data.avatar; userStore.user.avatar = res.data.avatar;
userStore.user.nickname = res.data.nickname; userStore.user.nickname = res.data.nickname;
userStore.user.status = res.data.status; userStore.user.status = res.data.status;
userStore.token = res.data.access_token;
message.success(t('login.loginSuccess')); message.success(t('login.loginSuccess'));
loginLoading.value = false; loginLoading.value = false;
showAccountRotateCaptcha.value = false; showAccountRotateCaptcha.value = false;

View File

@@ -21,7 +21,7 @@
class="qrlogin-card-qr" class="qrlogin-card-qr"
:size="280" :size="280"
:error-level="'H'" :error-level="'H'"
:status="status" :status="qrStatus"
@refresh="getQrCode" @refresh="getQrCode"
:value=qrcode :value=qrcode
:icon="logo" :icon="logo"
@@ -46,20 +46,20 @@ import {useI18n} from "vue-i18n";
import BoxDog from "@/components/BoxDog/BoxDog.vue"; import BoxDog from "@/components/BoxDog/BoxDog.vue";
import QRLoginFooter from "@/views/QRLogin/QRLoginFooter.vue"; import QRLoginFooter from "@/views/QRLogin/QRLoginFooter.vue";
import {useRouter} from 'vue-router'; import {useRouter} from 'vue-router';
import {generateQrCode} from "@/api/oauth/wechat.ts";
import logo from "@/assets/svgs/logo-album.svg"; import logo from "@/assets/svgs/logo-album.svg";
import useStore from "@/store"; import useStore from "@/store";
import {message} from "ant-design-vue"; import {message} from "ant-design-vue";
import {getUserDevice} from "@/api/user";
import BackgroundAnimation from "@/components/BackgroundAnimation/BackgroundAnimation.vue"; import BackgroundAnimation from "@/components/BackgroundAnimation/BackgroundAnimation.vue";
import {generateQrCode, wechatOffiaccountLoginApi} from "@/api/user";
import {WechatOffiaccountLogin} from "@/types/user";
const {t} = useI18n(); const {t} = useI18n();
const router = useRouter(); const router = useRouter();
const qrcode = ref<string>(''); const qrcode = ref<string>('');
const status = ref<string>('loading'); const qrStatus = ref<string>('loading');
const websocket = useStore().websocket; const websocket = useStore().websocket;
const userStore = useStore().user; const userStore = useStore().user;
@@ -73,7 +73,7 @@ async function getQrCode() {
qrcode.value = res.data; qrcode.value = res.data;
await handleListenMessage(); await handleListenMessage();
} else { } else {
status.value = 'expired'; qrStatus.value = 'expired';
} }
} }
@@ -92,15 +92,20 @@ async function handleListenMessage() {
// 注册消息接收处理函数 // 注册消息接收处理函数
websocket.on('message', async (res: any) => { websocket.on('message', async (res: any) => {
if (res && res.code === 200) { if (res && res.code === 200) {
status.value = 'scanned'; qrStatus.value = 'scanned';
const {data} = res; const {openid, client_id } = res.data;
userStore.user.uid = data.uid; const param: WechatOffiaccountLogin = {
userStore.user.access_token = data.access_token; openid: openid,
userStore.user.username = data.username; client_id: client_id
userStore.user.avatar = data.avatar; };
userStore.user.nickname = data.nickname; const response: any = await wechatOffiaccountLoginApi(param);
userStore.user.status = data.status; const {uid, access_token, username, avatar, nickname, status} = response.data;
await getUserDevice(data.access_token); userStore.user.uid = uid;
userStore.user.username = username;
userStore.user.avatar = avatar;
userStore.user.nickname = nickname;
userStore.user.status = status;
userStore.token = access_token;
message.success(t('login.loginSuccess')); message.success(t('login.loginSuccess'));
setTimeout(() => { setTimeout(() => {
router.push('/main/photo/all'); router.push('/main/photo/all');
@@ -122,9 +127,9 @@ watch(
() => websocket.readyState, () => websocket.readyState,
(newStatus) => { (newStatus) => {
if (newStatus === WebSocket.OPEN) { if (newStatus === WebSocket.OPEN) {
status.value = 'active'; qrStatus.value = 'active';
} else { } else {
status.value = 'expired'; qrStatus.value = 'expired';
} }
} }
); );

View File

@@ -29,7 +29,7 @@ const upscale = useStore().upscale;
const img = new Image(); const img = new Image();
const wsOptions = { const wsOptions = {
url: import.meta.env.VITE_FILE_SOCKET_URL + "?user_id=" + user.user.uid, url: import.meta.env.VITE_FILE_SOCKET_URL + "?user_id=" + user.user.uid,
protocols: [user.user.access_token], protocols: [user.token],
}; };
onMounted(() => { onMounted(() => {