user.ts 4.0 KB

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