user.ts 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. import { computed, ref } from "vue";
  2. import { forInObject, isNull, isObject, parse, storage } from "../utils";
  3. import { router } from "../router";
  4. import { request } from "../service";
  5. import type { UserInfo } from "../types";
  6. import { type LoginData, getUsersInfo } from "@/services/user";
  7. import { dict } from "./dict";
  8. export type Token = {
  9. token: string; // 访问token
  10. expire: number; // token过期时间(秒)
  11. refreshToken: string; // 刷新token
  12. refreshExpire: number; // 刷新token过期时间(秒)
  13. };
  14. export class User {
  15. /**
  16. * 用户信息,响应式对象
  17. */
  18. info = ref<UserInfo | null>(null);
  19. /**
  20. * 当前token,字符串或null
  21. */
  22. token: string | 'Basic ZW5kOmVuZA==';
  23. constructor() {
  24. // 获取本地用户信息
  25. const userInfo = storage.get("userInfo");
  26. // 获取本地token
  27. const token = storage.get("token") as string | 'Basic ZW5kOmVuZA==';
  28. // 如果token为空字符串则置为null
  29. this.token = token == "" ? 'Basic ZW5kOmVuZA==' : token;
  30. // 初始化用户信息
  31. if (userInfo != null && isObject(userInfo)) {
  32. this.set(userInfo);
  33. } else {
  34. this.get()
  35. }
  36. }
  37. /**
  38. * 获取用户信息(从服务端拉取最新信息并更新本地)
  39. * @returns Promise<void>
  40. */
  41. async get() {
  42. try {
  43. const res = await getUsersInfo()
  44. if (res != null) {
  45. this.set(res);
  46. }
  47. } catch (err) {
  48. this.logout();
  49. }
  50. }
  51. /**
  52. * 设置用户信息并存储到本地
  53. * @param data 用户信息对象
  54. */
  55. set(data: any) {
  56. if (isNull(data)) {
  57. return;
  58. }
  59. // 设置
  60. this.info.value = parse<UserInfo>(data)!;
  61. // 持久化到本地存储
  62. storage.set("userInfo", data, 0);
  63. }
  64. /**
  65. * 更新用户信息(本地与服务端同步)
  66. * @param data 新的用户信息
  67. */
  68. async update(data: any) {
  69. if (isNull(data) || isNull(this.info.value)) {
  70. return;
  71. }
  72. // 本地同步更新
  73. forInObject(data, (value, key) => {
  74. this.info.value![key] = value;
  75. });
  76. // 同步到服务端
  77. await request({
  78. url: "/app/user/info/updatePerson",
  79. method: "POST",
  80. data
  81. });
  82. }
  83. /**
  84. * 移除用户信息
  85. */
  86. remove() {
  87. this.info.value = null;
  88. storage.remove("userInfo");
  89. }
  90. /**
  91. * 判断用户信息是否为空
  92. * @returns boolean
  93. */
  94. isNull() {
  95. return this.info.value == null;
  96. }
  97. /**
  98. * 清除本地所有用户信息和token
  99. */
  100. clear() {
  101. storage.remove("userInfo");
  102. storage.remove("token");
  103. // storage.remove("refreshToken");
  104. this.token = 'Basic ZW5kOmVuZA==';
  105. this.remove();
  106. }
  107. /**
  108. * 退出登录,清除所有信息并跳转到登录页
  109. */
  110. logout() {
  111. this.clear();
  112. router.login();
  113. }
  114. /**
  115. * 设置token并存储到本地
  116. * @param data Token对象
  117. */
  118. setToken(data: LoginData) {
  119. this.token = `Bearer ${data?.access_token}`;
  120. // 访问token,提前5秒过期,防止边界问题
  121. storage.set("token", this.token, 7 * 24 * 60 * 60 - 5);
  122. this.get();
  123. dict.refresh();
  124. // 刷新token,提前5秒过期
  125. // storage.set("refreshToken", data.refresh_token, data.refreshExpire - 5);
  126. }
  127. // /**
  128. // * 刷新token(调用服务端接口,自动更新本地token)
  129. // * @returns Promise<string> 新的token
  130. // */
  131. // refreshToken(): Promise<string> {
  132. // return new Promise((resolve, reject) => {
  133. // request({
  134. // url: "/app/user/login/refreshToken",
  135. // method: "POST",
  136. // data: {
  137. // refreshToken: storage.get("refreshToken")
  138. // }
  139. // })
  140. // .then((res) => {
  141. // if (res != null) {
  142. // const token = parse<Token>(res);
  143. // if (token != null) {
  144. // this.setToken(token);
  145. // resolve(token.token);
  146. // }
  147. // }
  148. // })
  149. // .catch((err) => {
  150. // reject(err);
  151. // });
  152. // });
  153. // }
  154. }
  155. /**
  156. * 单例用户对象,项目全局唯一
  157. */
  158. export const user = new User();
  159. /**
  160. * 用户信息,响应式对象
  161. */
  162. export const userInfo = computed(() => user.info.value);