♻️ 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 {AccountLogin, PhoneLogin, ResetPassword} from "@/types/user";
import {AccountLogin, PhoneLogin, ResetPassword, WechatOffiaccountLogin} from "@/types/user";
/**
* 刷新token
@@ -8,7 +8,7 @@ export const refreshToken = () => {
return service.Post('/api/auth/token/refresh', {}, {
meta: {
authRole: 'refreshToken',
ignoreToken: true,
ignoreToken: false,
signature: true
}
});
@@ -89,16 +89,14 @@ export const resetPasswordApi = (param: ResetPassword) => {
}
);
};
/**
* 获取用户设备信息
* @param access_token
* 微信扫码登录
* @param param
*/
export const getUserDevice = (access_token: string) => {
return service.Post('/api/user/device',
{
access_token: access_token,
export const wechatOffiaccountLoginApi = (param: WechatOffiaccountLogin) => {
return service.Post('/api/user/wechat/offiaccount/login', {
openid: param.openid,
client_id: param.client_id,
},
{
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) => {
// start();
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;
// 检查用户是否已登录

View File

@@ -1,24 +1,20 @@
import {defineStore} from 'pinia';
import {reactive} from 'vue';
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 {useI18n} from "vue-i18n";
import {getGiteeUrl, getGithubUrl, getQQUrl} from "@/api/oauth";
export const useAuthStore = defineStore(
'user',
() => {
const user: any = reactive({
access_token: '',
uid: '',
username: '',
nickname: '',
avatar: '',
status: '',
});
const token: any = ref<string>('');
const clientId = ref<string>('');
const githubRedirectUrl = ref<string>('');
const giteeRedirectUrl = ref<string>('');
@@ -74,14 +70,13 @@ export const useAuthStore = defineStore(
if (typeof e.data === 'string') {
const res: any = JSON.parse(e.data);
if (res && res.code === 200) {
const {data} = res;
user.uid = data.uid;
user.access_token = data.access_token;
user.username = data.username;
user.avatar = data.avatar;
user.nickname = data.nickname;
user.status = data.status;
await getUserDevice(data.access_token);
const {uid, access_token, username, avatar, nickname, status} = res.data;
user.uid = uid;
user.username = username;
user.avatar = avatar;
user.nickname = nickname;
user.status = status;
token.value = access_token;
message.success(t('login.loginSuccess'));
window.removeEventListener("message", messageHandler);
setTimeout(() => {
@@ -130,9 +125,19 @@ export const useAuthStore = defineStore(
window.addEventListener("message", messageHandler);
}
function clear() {
token.value = "";
user.avatar = "";
user.uid = "";
user.username = "";
user.nickname = "";
user.status = "";
}
return {
user,
token,
clientId,
getGithubRedirectUrl,
getGiteeRedirectUrl,
@@ -141,6 +146,7 @@ export const useAuthStore = defineStore(
openGithubUrl,
openGiteeUrl,
openQQUrl,
clear
};
},
{
@@ -154,7 +160,7 @@ export const useAuthStore = defineStore(
persist: true,
storage: localStorage,
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;
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 res: any = await refreshToken();
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) => {
if (!method.meta?.ignoreToken) {
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;
method.config.headers['Accept-Language'] = lang.lang || 'zh';
@@ -72,11 +73,9 @@ export const service = createAlova({
}, 1000);
},
});
return Promise.reject(response.data);
return Promise.reject();
}
return response.data;
},
onError:
(error: AxiosError, _method: any) => {

View File

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

View File

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

View File

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

View File

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