mirror of
https://gitee.com/ulthon/ulthon_admin.git
synced 2026-07-08 02:52:49 +08:00
feat(uniapp): 登录后立即获取用户资料并优化应用启动流程
This commit is contained in:
@@ -1,13 +1,15 @@
|
|||||||
<script>
|
<script>
|
||||||
|
import { pinia } from './store'
|
||||||
|
import { useUserStore } from './store/user'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
onLaunch: function () {
|
onLaunch: function () {
|
||||||
console.log('App Launch')
|
useUserStore(pinia).bootstrap({ forceProfile: true })
|
||||||
},
|
},
|
||||||
onShow: function () {
|
onShow: function () {
|
||||||
console.log('App Show')
|
useUserStore(pinia).bootstrap({ forceProfile: false })
|
||||||
},
|
},
|
||||||
onHide: function () {
|
onHide: function () {
|
||||||
console.log('App Hide')
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
userStore.setToken(token)
|
userStore.setToken(token)
|
||||||
|
await userStore.fetchProfile({ force: true })
|
||||||
uni.showToast({ title: '登录成功', icon: 'none' })
|
uni.showToast({ title: '登录成功', icon: 'none' })
|
||||||
|
|
||||||
uni.navigateBack({
|
uni.navigateBack({
|
||||||
|
|||||||
@@ -11,6 +11,37 @@
|
|||||||
</view>
|
</view>
|
||||||
</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" />
|
<up-button type="primary" text="重新登录" @click="goLogin" />
|
||||||
<view style="height: 16rpx" />
|
<view style="height: 16rpx" />
|
||||||
<up-button type="error" text="退出登录" @click="logout" />
|
<up-button type="error" text="退出登录" @click="logout" />
|
||||||
@@ -32,12 +63,20 @@ export default {
|
|||||||
isLoggedIn() {
|
isLoggedIn() {
|
||||||
return this.userStore.isLoggedIn
|
return this.userStore.isLoggedIn
|
||||||
},
|
},
|
||||||
|
profile() {
|
||||||
|
return this.userStore.profile || {}
|
||||||
|
},
|
||||||
|
profileLoading() {
|
||||||
|
return this.userStore.profileLoading
|
||||||
|
},
|
||||||
},
|
},
|
||||||
onShow() {
|
onShow() {
|
||||||
this.userStore.init()
|
this.userStore.init()
|
||||||
if (!this.isLoggedIn) {
|
if (!this.isLoggedIn) {
|
||||||
this.goLogin()
|
this.goLogin()
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
this.userStore.fetchProfile({ force: true })
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
goLogin() {
|
goLogin() {
|
||||||
|
|||||||
@@ -1,11 +1,99 @@
|
|||||||
import { defineStore } from 'pinia'
|
import { defineStore } from 'pinia'
|
||||||
|
import { env } from '../config/env'
|
||||||
|
|
||||||
const TOKEN_KEY = 'ULTHON_ADMIN_TOKEN'
|
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', {
|
export const useUserStore = defineStore('user', {
|
||||||
state: () => ({
|
state: () => ({
|
||||||
token: '',
|
token: '',
|
||||||
inited: false,
|
inited: false,
|
||||||
|
profile: null,
|
||||||
|
profileFetchedAt: 0,
|
||||||
|
profileLoading: false,
|
||||||
}),
|
}),
|
||||||
getters: {
|
getters: {
|
||||||
isLoggedIn: (state) => !!state.token,
|
isLoggedIn: (state) => !!state.token,
|
||||||
@@ -14,16 +102,90 @@ export const useUserStore = defineStore('user', {
|
|||||||
init() {
|
init() {
|
||||||
if (this.inited) return
|
if (this.inited) return
|
||||||
this.token = uni.getStorageSync(TOKEN_KEY) || ''
|
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
|
this.inited = true
|
||||||
},
|
},
|
||||||
|
async bootstrap(options = {}) {
|
||||||
|
this.init()
|
||||||
|
if (!this.token) return
|
||||||
|
await this.fetchProfile({ force: !!options.forceProfile })
|
||||||
|
},
|
||||||
setToken(token) {
|
setToken(token) {
|
||||||
this.token = token || ''
|
this.token = token || ''
|
||||||
uni.setStorageSync(TOKEN_KEY, this.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() {
|
logout() {
|
||||||
this.token = ''
|
this.token = ''
|
||||||
|
this.profile = null
|
||||||
|
this.profileFetchedAt = 0
|
||||||
uni.removeStorageSync(TOKEN_KEY)
|
uni.removeStorageSync(TOKEN_KEY)
|
||||||
|
uni.removeStorageSync(PROFILE_KEY)
|
||||||
|
uni.removeStorageSync(PROFILE_FETCHED_AT_KEY)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user