Files
shanxia2.0/miniprogram/stores/user.js
T

234 lines
6.6 KiB
JavaScript

import { defineStore } from 'pinia'
import { computed, ref } from 'vue'
import { AUTH_API, TOKEN_KEY, REFRESH_TOKEN_KEY, USER_INFO_KEY, PAGE_PATHS } from '@/config/api'
import { request, parseResponseJson } from '@/utils/request'
import { buildMiniEncryptedLoginBody } from '@/utils/loginRsa'
export const useUserStore = defineStore('user', () => {
const token = ref('')
const refreshToken = ref('')
const userInfo = ref(null)
const isLoading = ref(false)
const menuAll = ref(false)
const menuCodes = ref([])
function normalizeUserInfo(raw) {
if (!raw || typeof raw !== 'object') return raw || null
const avatarUrl =
raw.avatarUrl != null && String(raw.avatarUrl).trim()
? String(raw.avatarUrl).trim()
: raw.avatar_url != null && String(raw.avatar_url).trim()
? String(raw.avatar_url).trim()
: ''
return {
...raw,
avatarUrl
}
}
const isLoggedIn = computed(() => !!token.value && !!userInfo.value)
const userRole = computed(() => userInfo.value?.role || '')
/** 登录成功默认进入工作台 Tab */
const homePath = computed(() => PAGE_PATHS.workbench)
function checkLoginStatus() {
const savedToken = uni.getStorageSync(TOKEN_KEY)
const savedUserInfo = uni.getStorageSync(USER_INFO_KEY)
const savedRefreshToken = uni.getStorageSync(REFRESH_TOKEN_KEY)
const normalizedToken =
typeof savedToken === 'string' ? savedToken.trim() : savedToken ? String(savedToken).trim() : ''
let normalizedUserInfo = null
if (typeof savedUserInfo === 'string') {
try {
normalizedUserInfo = normalizeUserInfo(JSON.parse(savedUserInfo))
} catch (error) {
normalizedUserInfo = null
}
} else if (savedUserInfo && typeof savedUserInfo === 'object') {
normalizedUserInfo = normalizeUserInfo(savedUserInfo)
}
if (normalizedToken && normalizedUserInfo) {
token.value = normalizedToken
refreshToken.value = typeof savedRefreshToken === 'string' ? savedRefreshToken : ''
userInfo.value = normalizedUserInfo
return
}
token.value = ''
refreshToken.value = ''
userInfo.value = null
}
function setLoginInfo(data) {
token.value = data.token || ''
refreshToken.value = data.refreshToken || ''
userInfo.value = normalizeUserInfo(data.userInfo || null)
uni.setStorageSync(TOKEN_KEY, token.value)
uni.setStorageSync(REFRESH_TOKEN_KEY, refreshToken.value)
uni.setStorageSync(USER_INFO_KEY, userInfo.value)
}
async function fetchMenuCodes() {
if (!token.value || !String(token.value).trim()) {
menuAll.value = false
menuCodes.value = []
return
}
try {
const res = await request({
url: AUTH_API.MENU_CODES,
method: 'GET'
})
const result = parseResponseJson(res)
if (!result || result.code !== 200 || !result.data) {
menuAll.value = false
menuCodes.value = []
return
}
const data = result.data
menuAll.value = !!(data.all || data.isSuperAdmin)
menuCodes.value = Array.isArray(data.menuCodes)
? data.menuCodes.map((c) => String(c || '').trim()).filter(Boolean)
: []
} catch {
menuAll.value = false
menuCodes.value = []
}
}
async function login(params) {
isLoading.value = true
try {
const encryptedBody = await buildMiniEncryptedLoginBody(params.username, params.password)
const res = await request({
url: AUTH_API.LOGIN,
method: 'POST',
data: encryptedBody
})
const result = parseResponseJson(res)
if (result && result.code === 200 && result.data) {
setLoginInfo({
token: result.data.token,
refreshToken: result.data.refreshToken,
userInfo: result.data.userInfo
})
await fetchMenuCodes()
return true
}
uni.showToast({ title: (result && result.message) || '登录失败', icon: 'none' })
return false
} catch (error) {
uni.showToast({
title: (error && error.message) || '网络请求失败',
icon: 'none'
})
return false
} finally {
isLoading.value = false
}
}
/** 手机号快捷登录;loading 由登录页控制,此处不改 isLoading */
async function wechatLogin(params) {
try {
const res = await request({
url: AUTH_API.WECHAT_LOGIN,
method: 'POST',
data: {
loginCode: params.loginCode,
phoneCode: params.phoneCode
}
})
const result = parseResponseJson(res)
if (result && result.code === 200 && result.data) {
setLoginInfo({
token: result.data.token,
refreshToken: result.data.refreshToken,
userInfo: result.data.userInfo
})
await fetchMenuCodes()
return true
}
uni.showToast({ title: (result && result.message) || '登录失败', icon: 'none' })
return false
} catch (e) {
uni.showToast({ title: (e && e.message) || '登录失败', icon: 'none' })
return false
}
}
function clearLoginInfo() {
token.value = ''
refreshToken.value = ''
userInfo.value = null
uni.removeStorageSync(TOKEN_KEY)
uni.removeStorageSync(REFRESH_TOKEN_KEY)
uni.removeStorageSync(USER_INFO_KEY)
menuAll.value = false
menuCodes.value = []
}
async function logout() {
try {
await request({
url: AUTH_API.LOGOUT,
method: 'POST'
})
} catch (error) {
// ignore
} finally {
clearLoginInfo()
uni.reLaunch({ url: PAGE_PATHS.login })
}
}
function navigateToHome() {
uni.reLaunch({ url: homePath.value })
}
function updateUserInfo(info) {
if (!userInfo.value || !info) return
userInfo.value = normalizeUserInfo({ ...userInfo.value, ...info })
uni.setStorageSync(USER_INFO_KEY, userInfo.value)
}
async function refreshUserInfo() {
if (!token.value || !String(token.value).trim()) return
try {
const res = await request({
url: AUTH_API.CURRENT_USER,
method: 'GET'
})
const result = parseResponseJson(res)
if (result.code !== 200 || !result.data) return
userInfo.value = normalizeUserInfo(result.data)
uni.setStorageSync(USER_INFO_KEY, userInfo.value)
} catch {
// ignore
}
}
return {
token,
refreshToken,
userInfo,
isLoading,
menuAll,
menuCodes,
isLoggedIn,
userRole,
homePath,
checkLoginStatus,
login,
wechatLogin,
logout,
clearLoginInfo,
navigateToHome,
updateUserInfo,
refreshUserInfo,
fetchMenuCodes
}
})