refactor(uniapp): 重构工具函数和请求模块,提取通用逻辑

This commit is contained in:
augushong
2026-02-01 12:34:50 +08:00
parent 83e6803a0a
commit 180d9291a3
3 changed files with 52 additions and 95 deletions

View File

@@ -1,5 +1,5 @@
import { defineStore } from 'pinia'
import { env } from '../config/env'
import { request } from '../utils/request'
const TOKEN_KEY = 'ULTHON_ADMIN_TOKEN'
const PROFILE_KEY = 'ULTHON_ADMIN_PROFILE'
@@ -8,85 +8,6 @@ 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: '',
@@ -142,11 +63,12 @@ export const useUserStore = defineStore('user', {
this.profileLoading = true
this._profilePromise = (async () => {
try {
const res = await requestJson({
const res = await request({
url: '/admin/index/editAdmin',
method: 'GET',
data: { get_page_data: 1 },
token: this.token,
silent: true,
})
const payload = (res && res.data) || {}
@@ -162,8 +84,6 @@ export const useUserStore = defineStore('user', {
} 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
}

View File

@@ -20,4 +20,3 @@ export function toQueryString(params) {
const parts = Object.keys(data).map((key) => `${encodeURIComponent(key)}=${encodeURIComponent(data[key])}`)
return parts.join('&')
}

View File

@@ -1,10 +1,11 @@
import { env } from '../config/env'
import { pinia } from '../store'
import { useUserStore } from '../store/user'
const AUTH_REQUIRED_CODE = 40101
const AUTH_EXPIRED_CODE = 40102
const TOKEN_KEY = 'ULTHON_ADMIN_TOKEN'
function buildUrl(url) {
if (!url) return ''
if (/^https?:\/\//i.test(url)) return url
@@ -36,7 +37,46 @@ function redirectToLoginIfNeeded() {
})
}
export function request(options) {
async function getUserStoreSafely() {
try {
const mod = await import('../store/user')
if (!mod || typeof mod.useUserStore !== 'function') return null
const userStore = mod.useUserStore(pinia)
if (userStore && typeof userStore.init === 'function') {
userStore.init()
}
return userStore || null
} catch (e) {
return null
}
}
function getTokenFromStorage() {
try {
return uni.getStorageSync(TOKEN_KEY) || ''
} catch (e) {
return ''
}
}
function clearTokenFromStorage() {
try {
uni.removeStorageSync(TOKEN_KEY)
} catch (e) {
}
}
async function handleAuthFailed() {
const userStore = await getUserStoreSafely()
if (userStore && typeof userStore.logout === 'function') {
userStore.logout()
} else {
clearTokenFromStorage()
}
redirectToLoginIfNeeded()
}
export async function request(options) {
const url = buildUrl(options.url)
const method = (options.method || 'GET').toUpperCase()
@@ -45,9 +85,8 @@ export function request(options) {
...(options.header || {}),
}
const userStore = useUserStore(pinia)
userStore.init()
const token = userStore.token
const silent = !!options.silent
const token = (options && options.token) || getTokenFromStorage()
if (token && !header.Authorization) {
header.Authorization = `Bearer ${token}`
}
@@ -67,13 +106,13 @@ export function request(options) {
const resData = res.data
if (!res || typeof res !== 'object') {
uni.showToast({ title: '请求失败', icon: 'none' })
if (!silent) uni.showToast({ title: '请求失败', icon: 'none' })
reject(new Error('Invalid response'))
return
}
if (res.statusCode && res.statusCode >= 400) {
uni.showToast({ title: `请求错误(${res.statusCode})`, icon: 'none' })
if (!silent) uni.showToast({ title: `请求错误(${res.statusCode})`, icon: 'none' })
reject(new Error(`HTTP ${res.statusCode}`))
return
}
@@ -85,11 +124,10 @@ export function request(options) {
}
if (resData.code === AUTH_REQUIRED_CODE || resData.code === AUTH_EXPIRED_CODE) {
userStore.logout()
redirectToLoginIfNeeded()
void handleAuthFailed()
}
uni.showToast({ title: resData.msg || '请求失败', icon: 'none' })
if (!silent) uni.showToast({ title: resData.msg || '请求失败', icon: 'none' })
reject(resData)
return
}
@@ -97,7 +135,7 @@ export function request(options) {
resolve(resData)
},
fail: (err) => {
uni.showToast({ title: '网络异常', icon: 'none' })
if (!silent) uni.showToast({ title: '网络异常', icon: 'none' })
reject(err)
},
})