2026-05-29 20:39:12 +08:00

166 lines
4.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { defineStore } from 'pinia';
import { ref, computed } from 'vue';
import { setCache, getCache, removeCache } from '@/utils/cache';
import { useParentStore } from '@/state/modules/parent';
import {
psdLogin as psdLoginApi,
parentSmsLogin as parentSmsLoginApi,
getUserInfo as getUserInfoApi,
selectUser as selectUserApi,
logout as logoutApi,
type AccountLoginParams,
type ParentSmsLoginParams,
} from '@/api/login';
export interface UserInfo {
id?: string;
account?: string;
nickName?: string;
avatarUrl?: string;
learnGradeId?: string;
schoolName?: string;
className?: string;
classId?: string;
diamond?: number;
experience?: number;
schoolClass?: any[];
[key: string]: any;
}
/**
* 学生用户 store兼容老接口
*/
export const useUserStore = defineStore('user', () => {
const userInfo = ref<UserInfo>(getCache('userInfo') || {});
const token = ref<string>(getCache('token') || '');
const isLogin = computed(() => !!token.value);
const gradeId = computed(() => userInfo.value.learnGradeId || '');
/** 清空登录态与缓存 */
const clear = async () => {
token.value = '';
userInfo.value = {};
removeCache('token');
removeCache('userInfo');
removeCache('teacherInfo');
removeCache('role');
removeCache('parentActiveChildId');
useParentStore().clear();
};
/** 拉取并解析用户信息 */
const fetchUserInfo = async () => {
try {
const res = await getUserInfoApi();
const info: UserInfo = res.data || {};
// schoolClass 字段后端有时是 JSON 字符串
if (typeof info.schoolClass === 'string') {
try {
info.schoolClass = JSON.parse(info.schoolClass);
} catch {
info.schoolClass = [];
}
}
// 提取学校班级到顶层方便展示
if (Array.isArray(info.schoolClass) && info.schoolClass.length) {
const school = info.schoolClass[0];
info.schoolName = school?.schoolName || '';
const cls = school?.classList?.[0];
if (cls) {
info.className = cls.className;
info.classId = cls.classId;
}
}
userInfo.value = info;
setCache('userInfo', info);
return info;
} catch (err) {
console.error('[user] fetchUserInfo error', err);
throw err;
}
};
/** 账号密码登录 */
const accountLogin = async (data: AccountLoginParams) => {
await clear();
setCache('role', data.clientType === 'MANAGE' ? 'teacher' : 'student');
const res = await psdLoginApi(data);
token.value = res.data;
setCache('token', res.data);
await fetchUserInfo();
};
/** 家长端 - 拉取并保存当前用户信息 */
const fetchParentUserInfo = async () => {
try {
const res = await selectUserApi();
const info: UserInfo = res.data || {};
userInfo.value = info;
setCache('userInfo', info);
return info;
} catch (err) {
console.error('[user] fetchParentUserInfo error', err);
throw err;
}
};
/** 家长端 - 保存登录 token */
const saveParentSession = (accessToken: string) => {
if (!accessToken?.trim()) {
throw new Error('登录失败');
}
token.value = accessToken;
setCache('token', accessToken);
setCache('role', 'parent');
};
/** 家长端 - 微信授权已绑定,写入 token */
const parentMpLoginSuccess = async (accessToken: string) => {
await clear();
saveParentSession(accessToken);
};
/** 家长端 - 手机号验证码登录 */
const parentLogin = async (data: ParentSmsLoginParams) => {
await clear();
const res = await parentSmsLoginApi(data);
saveParentSession(res.data);
};
/** 退出登录 */
const logout = async () => {
try {
await logoutApi();
} catch (e) {
console.warn('[user] logout api error', e);
}
await clear();
uni.reLaunch({ url: '/pages/index/index' });
};
/** 部分更新本地用户信息 */
const updateUserInfo = (info: Partial<UserInfo>) => {
userInfo.value = { ...userInfo.value, ...info };
setCache('userInfo', userInfo.value);
};
return {
userInfo,
token,
isLogin,
gradeId,
accountLogin,
parentMpLoginSuccess,
parentLogin,
fetchUserInfo,
fetchParentUserInfo,
logout,
clear,
updateUserInfo,
};
});