import { getTenantList, smsLogin } from '@/api/login'; import { to } from 'await-to-js'; import { getToken, removeToken, setToken, getClientId, setClientId } from '@/utils/auth'; import { login as loginApi, smsLogin as smsLoginApi, logout as logoutApi, getInfo as getUserInfo, getLoginUrl, sendGotoUrl, getSXZWFWLoginToken } from '@/api/login'; import { LoginData } from '@/api/types'; import useTagsViewStore from './tagsView'; import defAva from '@/assets/images/profile.jpg'; import store from '@/store'; import router from '../../router'; import axios from 'axios'; export interface LoginPayload { wbjKey: string; loginUrl: string; username?: string; password?: string; rememberMe?: boolean; code?: string; // 图形验证码 or 短信验证码通用字段 uuid?: string; phone?: string; phoneCode?: string; // 短信验证码专用(前端展示用) } export const useUserStore = defineStore('user', () => { const token = ref(getToken()); const client_id = ref(getClientId()); const name = ref(''); const nickname = ref(''); const userId = ref(''); const tenantId = ref(''); const isInStore = ref(false); const avatar = ref(''); const roles = ref>([]); // 用户角色编码集合 → 判断路由权限 const permissions = ref>([]); // 用户权限编码集合 → 判断按钮权限 const tenantList = ref([]); const isFirstLogin = ref(0); /** * 登录 * @param userInfo * @returns */ const login = async (userInfo: LoginData): Promise => { const [err, res] = await to(loginApi(userInfo)); if (res) { const data = res.data; setToken(data.access_token); token.value = data.access_token; return Promise.resolve(); } return Promise.reject(err); }; // 获取用户信息 const getInfo = async (): Promise => { const [err, res] = await to(getUserInfo()); if (res) { const data = res.data; const user = data.user; const profile = user.avatar == '' || user.avatar == null ? defAva : user.avatar; if (data.roles && data.roles.length > 0) { // 验证返回的roles是否是一个非空数组 roles.value = data.roles; permissions.value = data.permissions; } else { roles.value = ['ROLE_DEFAULT']; } isFirstLogin.value = user.isFirstLogin || 0; name.value = user.userName; isInStore.value = user.certification || false; nickname.value = user.nickName; avatar.value = profile; userId.value = user.userId; tenantId.value = user.tenantId; return Promise.resolve(); } return Promise.reject(err); }; // 注销 const logout = async (): Promise => { await logoutApi(); await toLoginPage(roles.value); token.value = ''; roles.value = []; permissions.value = []; removeToken(); }; const setAvatar = (value: string) => { avatar.value = value; }; const toLoginPage = async (this_roles) => { let res = await getTenantList(); let url: string = ''; if (tenantId.value === '000000') { url = '/admin/login'; } else { let item = res.data.voList.find((e) => e.tenantId == tenantId.value); if (item?.domain) { let otherPath = this_roles.includes('expert') ? '/expert' : '/org'; url = `/${item.domain}${otherPath}/login`; } else { url = '/login'; } } useTagsViewStore().visitedViews = []; router.push(url); }; const sendGotoUrlToBack = async () => { localStorage.setItem('goto', location.href); let res = await sendGotoUrl(''); location.href = res.data; }; function getHashSearchParam(url, key) { // 获取 hash 值,不包含 '#' 号 const hash = url.substring(url.indexOf('#') + 1); // 查找 '?' 号所在的索引 const searchIndex = hash.indexOf('?'); // '?' 号后面接的是索引参数,如果找到则+1,去除'?' 号 const search = searchIndex !== -1 ? hash.substring(searchIndex + 1) : ''; // 把搜索参数字符串提过URLSearchParams转成对象形式 const usp = new URLSearchParams(search); // 通过URLSearchParams自带的get方法,查询键所对应的值 return usp.get(key); } const callbackBySXZWFW = async () => { let clientId = getHashSearchParam(location.href, 'clientId'); let gotoUrl = getHashSearchParam(location.href, 'goto'); let wbjKey = gotoUrl && gotoUrl != 'null' ? localStorage.getItem('wbjKey') || '' : ''; let accType = getHashSearchParam(location.href, 'accType'); let acctType = getHashSearchParam(location.href, 'acctType'); let itype = getHashSearchParam(location.href, 'itype'); let accessLink = getHashSearchParam(location.href, 'accessLink'); if (clientId && accType && acctType && itype && accessLink) { let params_url = `wbjKey=${wbjKey}&clientId=${clientId}&accType=${accType}&acctType=${acctType}&itype=${itype}&accessLink=${accessLink}`; let res = await getSXZWFWLoginToken(params_url); const data = res.data; setToken(data.access_token); client_id.value = data.client_id; setClientId(data.client_id); token.value = data.access_token; return ''; } return `/${localStorage.getItem('wbjKey')}/expert/login`; }; const initTenantList = async () => { const { data } = await getTenantList(); tenantList.value = data.voList; }; /** * 短信验证码登录 * @param payload - 包含 wbjKey、phone 和 code * @returns Promise */ const smsLogin = async (data: LoginData): Promise => { const [err, res] = await to(smsLoginApi(data)); if (res) { const tokenData = res.data; setToken(tokenData.access_token); token.value = tokenData.access_token; await getInfo(); // 建议统一 return Promise.resolve(); } return Promise.reject(err); }; /** * 发送短信验证码 * @param payload - 包含 wbjKey 和 phone * @returns Promise */ const sendSmsCode = async (payload: { wbjKey: string; phone: string }): Promise => { const [err, res] = await to( fetch('/dev-api/auth/sms/send', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) }) ); if (res) { const data = await res.json(); if (data.code === 200) { return Promise.resolve(); } else { return Promise.reject(new Error(data.msg || '发送验证码失败')); } } return Promise.reject(err || new Error('发送请求失败')); }; return { userId, tenantId, client_id, token, nickname, avatar, roles, permissions, isInStore, tenantList, isFirstLogin, login, getInfo, logout, setAvatar, toLoginPage, sendGotoUrlToBack, callbackBySXZWFW, initTenantList, smsLogin, sendSmsCode, router: useRoute() }; }); export default useUserStore; // 非setup export function useUserStoreHook() { return useUserStore(store); }