Files

192 lines
3.9 KiB
TypeScript
Raw Permalink Normal View History

import { computed, ref } from "vue";
import { forInObject, isNull, isObject, parse, storage } from "../utils";
2025-07-21 16:47:04 +08:00
import { router } from "../router";
import { request } from "../service";
import type { UserInfo } from "@/types";
2025-07-21 16:47:04 +08:00
export type Token = {
token: string; // 访问token
expire: number; // token过期时间
refreshToken: string; // 刷新token
refreshExpire: number; // 刷新token过期时间
2025-07-21 16:47:04 +08:00
};
export class User {
/**
*
2025-07-21 16:47:04 +08:00
*/
info = ref<UserInfo | null>(null);
2025-07-21 16:47:04 +08:00
/**
* tokennull
*/
token: string | null = null;
constructor() {
// 获取本地用户信息
const userInfo = storage.get("userInfo");
// 获取本地token
const token = storage.get("token") as string | null;
// 如果token为空字符串则置为null
this.token = token == "" ? null : token;
// 初始化用户信息
if (userInfo != null && isObject(userInfo)) {
this.set(userInfo);
}
2025-07-21 16:47:04 +08:00
}
/**
*
* @returns Promise<void>
*/
async get() {
if (this.token != null) {
2026-01-21 01:37:34 +08:00
// 如果是模拟token则跳过远程获取防止由于后端校验失败导致的自动退出登录
if (this.token.startsWith("fake-")) {
return;
}
await request({
2026-01-21 01:37:34 +08:00
url: "/api/nongchuang/user/info"
})
2025-07-21 16:47:04 +08:00
.then((res) => {
if (res != null) {
2026-01-21 01:37:34 +08:00
this.set(res.userInfo || res); // Adapt to the map structure { userInfo: ..., stats: ... } or flat
2025-07-21 16:47:04 +08:00
}
})
.catch(() => {
2026-01-21 01:37:34 +08:00
this.logout();
2025-07-21 16:47:04 +08:00
});
}
}
/**
*
* @param data
*/
set(data: any) {
if (isNull(data)) {
return;
}
// 设置
this.info.value = parse<UserInfo>(data)!;
2025-07-21 16:47:04 +08:00
// 持久化到本地存储
storage.set("userInfo", data, 0);
}
/**
*
* @param data
*/
async update(data: any) {
if (isNull(data) || isNull(this.info.value)) {
2025-07-21 16:47:04 +08:00
return;
}
// 本地同步更新
forInObject(data, (value, key) => {
this.info.value![key] = value;
2025-07-21 16:47:04 +08:00
});
// 同步到服务端
await request({
2026-01-21 01:37:34 +08:00
url: "/api/nongchuang/user/info",
method: "PUT",
data
});
2025-07-21 16:47:04 +08:00
}
/**
*
2025-07-21 16:47:04 +08:00
*/
remove() {
this.info.value = null;
storage.remove("userInfo");
2025-07-21 16:47:04 +08:00
}
/**
*
2025-07-21 16:47:04 +08:00
* @returns boolean
*/
isNull() {
return this.info.value == null;
2025-07-21 16:47:04 +08:00
}
/**
* token
*/
clear() {
storage.remove("userInfo");
storage.remove("token");
storage.remove("refreshToken");
this.token = null;
this.remove();
}
/**
* 退
*/
logout() {
this.clear();
2026-01-21 01:37:34 +08:00
// 移除自动跳转,仅清除已过期的登录态,由页面自行决定是否引导登录
// router.login();
2025-07-21 16:47:04 +08:00
}
/**
* token并存储到本地
* @param data Token对象
*/
setToken(data: Token) {
this.token = data.token;
// 访问token提前5秒过期防止边界问题
storage.set("token", data.token, data.expire - 5);
// 刷新token提前5秒过期
storage.set("refreshToken", data.refreshToken, data.refreshExpire - 5);
}
/**
* tokentoken
* @returns Promise<string> token
*/
refreshToken(): Promise<string> {
return new Promise((resolve, reject) => {
request({
2026-01-21 01:37:34 +08:00
url: "/api/nongchuang/auth/refresh-token",
method: "POST",
2026-01-21 01:37:34 +08:00
params: {
2025-07-21 16:47:04 +08:00
refreshToken: storage.get("refreshToken")
}
})
2025-07-21 16:47:04 +08:00
.then((res) => {
if (res != null) {
const token = parse<Token>(res);
2025-07-21 16:47:04 +08:00
if (token != null) {
this.setToken(token);
resolve(token.token);
}
2025-07-21 16:47:04 +08:00
}
})
.catch((err) => {
reject(err);
});
});
}
}
/**
*
*/
export const user = new User();
/**
*
2025-07-21 16:47:04 +08:00
*/
export const userInfo = computed(() => user.info.value);