user.ts 3.6 KB

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