mirror of
https://gitee.com/ulthon/ulthon_admin.git
synced 2026-07-01 15:32:48 +08:00
feat(uniapp): 登录后立即获取用户资料并优化应用启动流程
This commit is contained in:
@@ -1,13 +1,15 @@
|
||||
<script>
|
||||
import { pinia } from './store'
|
||||
import { useUserStore } from './store/user'
|
||||
|
||||
export default {
|
||||
onLaunch: function () {
|
||||
console.log('App Launch')
|
||||
useUserStore(pinia).bootstrap({ forceProfile: true })
|
||||
},
|
||||
onShow: function () {
|
||||
console.log('App Show')
|
||||
useUserStore(pinia).bootstrap({ forceProfile: false })
|
||||
},
|
||||
onHide: function () {
|
||||
console.log('App Hide')
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -65,6 +65,7 @@ export default {
|
||||
}
|
||||
|
||||
userStore.setToken(token)
|
||||
await userStore.fetchProfile({ force: true })
|
||||
uni.showToast({ title: '登录成功', icon: 'none' })
|
||||
|
||||
uni.navigateBack({
|
||||
|
||||
@@ -11,6 +11,37 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="card">
|
||||
<view class="row">
|
||||
<view class="label">用户ID</view>
|
||||
<view class="value">{{ isLoggedIn ? (profile.id || '-') : '-' }}</view>
|
||||
</view>
|
||||
<view class="row">
|
||||
<view class="label">用户名</view>
|
||||
<view class="value">{{ isLoggedIn ? (profile.username || '-') : '-' }}</view>
|
||||
</view>
|
||||
<view class="row">
|
||||
<view class="label">昵称</view>
|
||||
<view class="value">{{ isLoggedIn ? (profile.nickname || '-') : '-' }}</view>
|
||||
</view>
|
||||
<view class="row">
|
||||
<view class="label">手机号</view>
|
||||
<view class="value">{{ isLoggedIn ? (profile.phone || '-') : '-' }}</view>
|
||||
</view>
|
||||
<view class="row">
|
||||
<view class="label">备注</view>
|
||||
<view class="value">{{ isLoggedIn ? (profile.remark || '-') : '-' }}</view>
|
||||
</view>
|
||||
<view class="row">
|
||||
<view class="label">头像</view>
|
||||
<view class="value">{{ isLoggedIn ? (profile.head_img || '-') : '-' }}</view>
|
||||
</view>
|
||||
<view class="row">
|
||||
<view class="label">读取状态</view>
|
||||
<view class="value">{{ isLoggedIn ? (profileLoading ? '读取中...' : '已读取') : '-' }}</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<up-button type="primary" text="重新登录" @click="goLogin" />
|
||||
<view style="height: 16rpx" />
|
||||
<up-button type="error" text="退出登录" @click="logout" />
|
||||
@@ -32,12 +63,20 @@ export default {
|
||||
isLoggedIn() {
|
||||
return this.userStore.isLoggedIn
|
||||
},
|
||||
profile() {
|
||||
return this.userStore.profile || {}
|
||||
},
|
||||
profileLoading() {
|
||||
return this.userStore.profileLoading
|
||||
},
|
||||
},
|
||||
onShow() {
|
||||
this.userStore.init()
|
||||
if (!this.isLoggedIn) {
|
||||
this.goLogin()
|
||||
return
|
||||
}
|
||||
this.userStore.fetchProfile({ force: true })
|
||||
},
|
||||
methods: {
|
||||
goLogin() {
|
||||
|
||||
@@ -1,11 +1,99 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import { env } from '../config/env'
|
||||
|
||||
const TOKEN_KEY = 'ULTHON_ADMIN_TOKEN'
|
||||
const PROFILE_KEY = 'ULTHON_ADMIN_PROFILE'
|
||||
const PROFILE_FETCHED_AT_KEY = 'ULTHON_ADMIN_PROFILE_FETCHED_AT'
|
||||
|
||||
const AUTH_REQUIRED_CODE = 40101
|
||||
const AUTH_EXPIRED_CODE = 40102
|
||||
|
||||
function buildUrl(url) {
|
||||
if (!url) return ''
|
||||
if (/^https?:\/\//i.test(url)) return url
|
||||
const baseUrl = env.apiBaseUrl || ''
|
||||
if (url.startsWith('/')) return `${baseUrl}${url}`
|
||||
return `${baseUrl}/${url}`
|
||||
}
|
||||
|
||||
function getCurrentRoutePath() {
|
||||
try {
|
||||
const pages = getCurrentPages()
|
||||
const current = pages && pages[pages.length - 1]
|
||||
const route = (current && (current.route || (current.$page && current.$page.fullPath))) || ''
|
||||
return String(route)
|
||||
} catch (e) {
|
||||
return ''
|
||||
}
|
||||
}
|
||||
|
||||
function redirectToLoginIfNeeded() {
|
||||
const route = getCurrentRoutePath()
|
||||
if (route.includes('pages/login/index')) return
|
||||
|
||||
uni.navigateTo({
|
||||
url: '/pages/login/index',
|
||||
fail: () => {
|
||||
uni.reLaunch({ url: '/pages/login/index' })
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
function requestJson(options) {
|
||||
const url = buildUrl(options.url)
|
||||
const method = (options.method || 'GET').toUpperCase()
|
||||
const header = {
|
||||
Accept: 'application/json',
|
||||
...(options.header || {}),
|
||||
}
|
||||
|
||||
if (options.token && !header.Authorization) {
|
||||
header.Authorization = `Bearer ${options.token}`
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
uni.request({
|
||||
url,
|
||||
method,
|
||||
data: options.data || {},
|
||||
header,
|
||||
timeout: options.timeout || env.timeout || 60000,
|
||||
success: (res) => {
|
||||
const resData = res.data
|
||||
|
||||
if (!res || typeof res !== 'object') {
|
||||
reject(new Error('Invalid response'))
|
||||
return
|
||||
}
|
||||
|
||||
if (res.statusCode && res.statusCode >= 400) {
|
||||
reject(new Error(`HTTP ${res.statusCode}`))
|
||||
return
|
||||
}
|
||||
|
||||
if (resData && typeof resData === 'object' && 'code' in resData) {
|
||||
if (resData.code === 0) {
|
||||
resolve(resData)
|
||||
return
|
||||
}
|
||||
reject(resData)
|
||||
return
|
||||
}
|
||||
|
||||
resolve(resData)
|
||||
},
|
||||
fail: (err) => reject(err),
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
export const useUserStore = defineStore('user', {
|
||||
state: () => ({
|
||||
token: '',
|
||||
inited: false,
|
||||
profile: null,
|
||||
profileFetchedAt: 0,
|
||||
profileLoading: false,
|
||||
}),
|
||||
getters: {
|
||||
isLoggedIn: (state) => !!state.token,
|
||||
@@ -14,16 +102,90 @@ export const useUserStore = defineStore('user', {
|
||||
init() {
|
||||
if (this.inited) return
|
||||
this.token = uni.getStorageSync(TOKEN_KEY) || ''
|
||||
this.profile = uni.getStorageSync(PROFILE_KEY) || null
|
||||
this.profileFetchedAt = Number(uni.getStorageSync(PROFILE_FETCHED_AT_KEY) || 0) || 0
|
||||
this.inited = true
|
||||
},
|
||||
async bootstrap(options = {}) {
|
||||
this.init()
|
||||
if (!this.token) return
|
||||
await this.fetchProfile({ force: !!options.forceProfile })
|
||||
},
|
||||
setToken(token) {
|
||||
this.token = token || ''
|
||||
uni.setStorageSync(TOKEN_KEY, this.token)
|
||||
if (!this.token) {
|
||||
this.profile = null
|
||||
this.profileFetchedAt = 0
|
||||
uni.removeStorageSync(PROFILE_KEY)
|
||||
uni.removeStorageSync(PROFILE_FETCHED_AT_KEY)
|
||||
}
|
||||
},
|
||||
async fetchProfile(options = {}) {
|
||||
this.init()
|
||||
if (!this.token) {
|
||||
this.profile = null
|
||||
this.profileFetchedAt = 0
|
||||
return null
|
||||
}
|
||||
|
||||
const now = Date.now()
|
||||
const cacheMs = Number(options.cacheMs || 60 * 1000) || 60 * 1000
|
||||
if (!options.force && this.profileFetchedAt && now - this.profileFetchedAt < cacheMs) {
|
||||
return this.profile
|
||||
}
|
||||
|
||||
if (this._profilePromise) {
|
||||
return this._profilePromise
|
||||
}
|
||||
|
||||
this.profileLoading = true
|
||||
this._profilePromise = (async () => {
|
||||
try {
|
||||
const res = await requestJson({
|
||||
url: '/admin/index/editAdmin',
|
||||
method: 'GET',
|
||||
data: { get_page_data: 1 },
|
||||
token: this.token,
|
||||
})
|
||||
|
||||
const payload = (res && res.data) || {}
|
||||
const profile = payload.row || payload.admin || payload.session_admin || null
|
||||
|
||||
this.profile = profile
|
||||
this.profileFetchedAt = Date.now()
|
||||
|
||||
uni.setStorageSync(PROFILE_KEY, this.profile || null)
|
||||
uni.setStorageSync(PROFILE_FETCHED_AT_KEY, this.profileFetchedAt)
|
||||
|
||||
return this.profile
|
||||
} catch (e) {
|
||||
const code = e && typeof e === 'object' ? e.code : null
|
||||
if (code === AUTH_REQUIRED_CODE || code === AUTH_EXPIRED_CODE) {
|
||||
this.logout()
|
||||
redirectToLoginIfNeeded()
|
||||
return null
|
||||
}
|
||||
|
||||
return this.profile
|
||||
} finally {
|
||||
this.profileLoading = false
|
||||
}
|
||||
})()
|
||||
|
||||
try {
|
||||
return await this._profilePromise
|
||||
} finally {
|
||||
this._profilePromise = null
|
||||
}
|
||||
},
|
||||
logout() {
|
||||
this.token = ''
|
||||
this.profile = null
|
||||
this.profileFetchedAt = 0
|
||||
uni.removeStorageSync(TOKEN_KEY)
|
||||
uni.removeStorageSync(PROFILE_KEY)
|
||||
uni.removeStorageSync(PROFILE_FETCHED_AT_KEY)
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user