userStore.ts 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. import { defineStore } from 'pinia';
  2. import { useTransferPage } from '@/hooks/useTransferPage';
  3. import { getUserInfo, logoutPhysical } from '@/api/modules/login';
  4. import config from '@/config';
  5. import type { Study, UserStoreState } from '@/types';
  6. import type { UserInfo, VipCardInfo } from '@/types/user';
  7. import tools from '@/utils/uni-tool';
  8. import defaultAvatar from '@/static/personal/avatar_default.png'
  9. import {CardType, EnumBindScene, EnumExamType, EnumReviewMode, EnumScoreLock, EnumUserType} from '@/common/enum';
  10. import { getDirectedSchool, saveDirectedSchool } from '@/api/modules/study';
  11. import { usePay } from '@/hooks/usePay';
  12. import { getUserBindCard } from '@/api/modules/user';
  13. const themeColor = '#31A0FC';
  14. type CheckLoginOptions = {
  15. askToLogin?: boolean;
  16. }
  17. export const useUserStore = defineStore('ie-user', {
  18. state: (): UserStoreState => ({
  19. accessToken: null,
  20. user: null,
  21. card: null,
  22. isDefaultModifyPwd: false,
  23. isPasswordExpired: false,
  24. isExamGuideShow: false,
  25. tempInfo: {
  26. location: '',
  27. examType: undefined,
  28. },
  29. org: {
  30. ...config.defaultOrg,
  31. },
  32. rememberPwd: false,
  33. cardPassword: '',
  34. cardNo: '',
  35. directedSchoolList: [],
  36. practiceSettings: {
  37. reviewMode: EnumReviewMode.AFTER_SUBMIT,
  38. autoNext: false
  39. }
  40. }),
  41. getters: {
  42. isLogin(state: UserStoreState): boolean {
  43. return !!state.accessToken && state.user !== null && Object.keys(state.user).length > 0;
  44. },
  45. userInfo(state: UserStoreState): UserInfo {
  46. return state.user || {} as UserInfo;
  47. },
  48. avatar(state: UserStoreState): string {
  49. return this.userInfo.avatar || defaultAvatar
  50. },
  51. nickName(state: UserStoreState): string {
  52. return this.userInfo.nickName || '游客'
  53. },
  54. anonymousPhoneNumber(state: UserStoreState): string {
  55. if (this.userInfo.phonenumber && this.userInfo.phonenumber.length === 11) {
  56. return this.userInfo.phonenumber.slice(0, 3) + '****' + this.userInfo.phonenumber.slice(7)
  57. }
  58. return '';
  59. },
  60. isVip(): boolean {
  61. if (!this.card) {
  62. return false;
  63. }
  64. const { outDate } = this.card;
  65. return !!this.userInfo.cardId && new Date(outDate) > new Date();
  66. },
  67. isExperienceVip(): boolean {
  68. if (!this.card) {
  69. return false;
  70. }
  71. const { outDate } = this.card;
  72. return this.card?.type === CardType.EXPERIENCE && new Date(outDate) > new Date();
  73. },
  74. vipInfo(state: UserStoreState): VipCardInfo {
  75. if (state.card) {
  76. return state.card;
  77. }
  78. return {} as VipCardInfo;
  79. },
  80. orgInfo(state: UserStoreState) {
  81. return state.org;
  82. },
  83. isStudent(): boolean {
  84. return this.userInfo.userType === EnumUserType.STUDENT;
  85. },
  86. isTeacher(): boolean {
  87. return this.userInfo.userType === EnumUserType.TEACHER;
  88. },
  89. isAgent(): boolean {
  90. return this.userInfo.userType === EnumUserType.AGENT;
  91. },
  92. isAuditor(): boolean {
  93. return false;
  94. return this.userInfo.accountType === 2;
  95. },
  96. hasDirectedSchool(): boolean {
  97. return this.directedSchoolList.length > 0;
  98. },
  99. hasTestAndRecord(): boolean {
  100. // 职高对口升学 目前不支持测评
  101. return this.getExamType != EnumExamType.VHS;
  102. },
  103. /**
  104. * 需要完成信息完善的用户类型
  105. * @returns
  106. */
  107. needCompleteInfo(): boolean {
  108. return this.isTeacher || this.isAgent;
  109. },
  110. // 兼容游客时显示
  111. getLocation(): string {
  112. if (this.isLogin) {
  113. return this.user?.location || '';
  114. }
  115. return this.tempInfo?.location || '';
  116. },
  117. getExamType(): string {
  118. if (this.isLogin) {
  119. return this.user?.examType || '';
  120. }
  121. return this.tempInfo?.examType || '';
  122. },
  123. isHN(): boolean {
  124. return this.getLocation == '湖南'
  125. },
  126. isVHS(): boolean {
  127. return this.getExamType === EnumExamType.VHS;
  128. },
  129. examMajorName(): string {
  130. return this.userInfo.examMajorName || '';
  131. },
  132. isScoreLocked(): boolean {
  133. return this.userInfo.scoreLock == EnumScoreLock.locked
  134. },
  135. isScoreUnlocked(): boolean {
  136. return this.userInfo.scoreLock == EnumScoreLock.unlock
  137. },
  138. isScoreLocking(): boolean {
  139. return this.userInfo.scoreLock == EnumScoreLock.locking
  140. },
  141. isBindWechat(): boolean {
  142. return !!this.userInfo.wxOpenId;
  143. }
  144. },
  145. actions: {
  146. setToken(token: string) {
  147. this.accessToken = token;
  148. },
  149. async login(token: string) {
  150. try {
  151. this.accessToken = token;
  152. const userInfo = await this.getUserInfo();;
  153. return Promise.resolve({
  154. success: true,
  155. userInfo: userInfo
  156. });
  157. } catch (error) {
  158. return Promise.resolve({
  159. success: false,
  160. userInfo: null
  161. });
  162. }
  163. },
  164. checkLogin({ askToLogin = true }: CheckLoginOptions = {}): Promise<boolean> {
  165. if (this.isLogin) {
  166. return Promise.resolve(true);
  167. }
  168. const { transferTo } = useTransferPage();
  169. return new Promise((resolve, reject) => {
  170. if (askToLogin) {
  171. tools.showModal({
  172. title: '提示',
  173. content: '当前未登录,是否前往登录?',
  174. confirmColor: themeColor
  175. }).then(confirm => {
  176. if (confirm) {
  177. transferTo('/pagesSystem/pages/login/login').then((res) => {
  178. resolve(res as boolean);
  179. }).catch(() => {
  180. resolve(false);
  181. });
  182. }
  183. });
  184. } else {
  185. transferTo('/pagesSystem/pages/login/login').then((res) => {
  186. resolve(res as boolean);
  187. }).catch(() => {
  188. resolve(false);
  189. });
  190. }
  191. });
  192. },
  193. checkVip() {
  194. return new Promise((resolve, reject) => {
  195. if (!this.isVip) {
  196. resolve(false);
  197. }
  198. resolve(true);
  199. });
  200. },
  201. /**
  202. * 检查老师是否完善信息
  203. * @returns
  204. */
  205. checkInfoTeacherComplete() {
  206. return new Promise((resolve, reject) => {
  207. if (this.needCompleteInfo && (!this.userInfo.location || !this.userInfo.examType || !this.userInfo.endYear)) {
  208. const { transferTo } = useTransferPage();
  209. transferTo('/pagesSystem/pages/bind-teacher-profile/bind-teacher-profile').then(res => {
  210. resolve(res as boolean);
  211. }).catch(() => {
  212. resolve(false);
  213. });
  214. } else {
  215. resolve(true);
  216. }
  217. });
  218. },
  219. /**
  220. * 检查学生是否需要完善信息
  221. * @returns
  222. */
  223. checkInfoStudentComplete(): Promise<boolean> {
  224. const { queryPayStatus } = usePay();
  225. return new Promise(async (resolve, reject) => {
  226. const payResult = await queryPayStatus();
  227. if (payResult && payResult.isPaySuccess) {
  228. const { data } = await getUserBindCard();
  229. if (data && data.cardNo && data.password) {
  230. const submitInfo = {
  231. token: this.accessToken,
  232. scene: EnumBindScene.LOGIN_BIND,
  233. userInfo: this.userInfo,
  234. cardInfo: data,
  235. registerInfo: {
  236. username: data.cardNo,
  237. password: data.password,
  238. }
  239. };
  240. const { transferTo } = useTransferPage();
  241. transferTo('/pagesSystem/pages/bind-profile/bind-profile', {
  242. data: submitInfo
  243. }).then(res => {
  244. resolve(res as boolean);
  245. }).catch(() => {
  246. resolve(false);
  247. });
  248. }
  249. } else {
  250. resolve(false);
  251. }
  252. });
  253. },
  254. async getUserInfo() {
  255. const res = await getUserInfo();
  256. const { data, isDefaultModifyPwd, isPasswordExpired, card, org } = res;
  257. if (data) {
  258. this.user = data;
  259. if (card) {
  260. this.card = card;
  261. }
  262. this.isDefaultModifyPwd = isDefaultModifyPwd;
  263. this.isPasswordExpired = isPasswordExpired;
  264. }
  265. if (org) {
  266. this.org = org;
  267. }
  268. const { getPrice } = usePay();
  269. getPrice();
  270. return data;
  271. },
  272. /**
  273. * 保存定向学校列表
  274. * @param list 定向学校列表
  275. */
  276. async saveDirectedSchoolList(list: Study.DirectedSchool[]) {
  277. await saveDirectedSchool(list);
  278. await this.getDirectedSchoolList();
  279. },
  280. /**
  281. * 获取定向学校列表
  282. */
  283. async getDirectedSchoolList() {
  284. const { data } = await getDirectedSchool();
  285. this.directedSchoolList = data || [];
  286. },
  287. setPracticeSettings(settings: Study.PracticeSettings) {
  288. this.practiceSettings = settings;
  289. },
  290. askLogout() {
  291. return new Promise((resolve, reject) => {
  292. uni.$ie.showModal({
  293. title: '提示',
  294. content: '确定退出登录吗?',
  295. confirmColor: themeColor
  296. }).then(confirm => {
  297. if (confirm) {
  298. this.logout();
  299. resolve(true);
  300. } else {
  301. resolve(false);
  302. }
  303. });
  304. });
  305. },
  306. rememberLoginInfo(remember: boolean, cardNo: string, cardPassword: string) {
  307. this.rememberPwd = remember;
  308. if (remember) {
  309. this.cardNo = cardNo;
  310. this.cardPassword = cardPassword;
  311. } else {
  312. this.cardNo = '';
  313. this.cardPassword = '';
  314. }
  315. },
  316. logout() {
  317. this.accessToken = null;
  318. this.user = null;
  319. this.isDefaultModifyPwd = false;
  320. this.isPasswordExpired = false;
  321. this.org = {
  322. ...config.defaultOrg,
  323. };
  324. const { transferTo, routes } = useTransferPage();
  325. setTimeout(() => {
  326. transferTo(routes.pageIndex, {
  327. type: 'reLaunch'
  328. });
  329. }, 0);
  330. },
  331. deleteAccount() {
  332. uni.$ie.showLoading('注销中...');
  333. logoutPhysical().then(() => {
  334. this.logout();
  335. }).finally(() => {
  336. uni.$ie.hideLoading();
  337. });
  338. },
  339. /**
  340. * 拨打客服电话
  341. * @returns
  342. */
  343. callContactPhone() {
  344. if (!this.orgInfo.contactPhone) {
  345. uni.$ie.showToast('暂无客服电话');
  346. return;
  347. }
  348. uni.showActionSheet({
  349. title: '客服电话',
  350. itemList: [`拨打电话:${this.orgInfo.contactPhone}`],
  351. success: (res) => {
  352. uni.makePhoneCall({
  353. phoneNumber: this.orgInfo.contactPhone
  354. });
  355. }
  356. });
  357. }
  358. },
  359. persist: {
  360. storage: {
  361. getItem: uni.getStorageSync,
  362. setItem: uni.setStorageSync,
  363. }
  364. }
  365. });