feat: 重构HTTP客户端架构和认证系统
核心改进: - HTTP客户端:工厂函数模式,支持自定义拦截器和401/403处理 - 认证服务:函数式实现,消除this绑定问题,支持业务码+HTTP状态码双通道 - Token管理:简化为直接实例导出,移除bind()和箭头函数包装 - 路由守卫:优化逻辑,移除冗余代码,更简洁易维护 技术亮点: - 统一401/403错误处理(业务code和HTTP status双检查) - 自动刷新token并重试请求,保留自定义拦截器 - 分层清晰:clientAxios (Mono) -> http (应用) -> AuthService - 支持扩展:业务代码可创建自定义HTTP实例并添加拦截器 文件变更: - 新增 AuthService.js (函数式) 和 Login.vue - 重构 http.js、token-manager.js、router/index.js - 删除 TokenInput.vue、utils/auth.js 等冗余文件 - 更新所有API调用点使用直接实例导入 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1,161 +0,0 @@
|
||||
# 公共 Hooks 模块
|
||||
|
||||
此目录包含可在 monorepo 各个应用中复用的 Vue Composition API Hooks。
|
||||
|
||||
## 📁 目录结构
|
||||
|
||||
```
|
||||
hooks/web/
|
||||
├── useCache.js # 缓存管理 Hook
|
||||
├── useUserInfo.js # 用户信息获取 Hook
|
||||
└── useVoiceText.ts # 语音文本处理 Hook(已抽离为公共模块)
|
||||
```
|
||||
|
||||
## 🚀 使用方式
|
||||
|
||||
### useUserInfo Hook
|
||||
|
||||
获取用户信息的公共 Hook,可在各个应用中复用。
|
||||
|
||||
#### 基础用法
|
||||
|
||||
```javascript
|
||||
import { useUserInfo } from '@gold/hooks/web/useUserInfo'
|
||||
import { getToken } from '@/utils/token-manager'
|
||||
|
||||
// 在组件中使用
|
||||
const { fetchUserInfo, loading, error, userInfo } = useUserInfo({
|
||||
getToken, // 传入获取 token 的函数
|
||||
})
|
||||
|
||||
// 获取用户信息
|
||||
await fetchUserInfo()
|
||||
```
|
||||
|
||||
#### 便捷函数
|
||||
|
||||
如果只需要获取一次用户信息,可以使用便捷函数:
|
||||
|
||||
```javascript
|
||||
import { getUserInfo } from '@gold/hooks/web/useUserInfo'
|
||||
import { getToken } from '@/utils/token-manager'
|
||||
|
||||
// 直接获取用户信息
|
||||
const userInfo = await getUserInfo({
|
||||
getToken,
|
||||
})
|
||||
```
|
||||
|
||||
#### 自定义配置
|
||||
|
||||
```javascript
|
||||
const { fetchUserInfo } = useUserInfo({
|
||||
baseUrl: '/custom-api/member', // 自定义 API 基础 URL
|
||||
getToken: () => {
|
||||
// 自定义获取 token 的逻辑
|
||||
return localStorage.getItem('token')
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
## 📝 API 说明
|
||||
|
||||
### useUserInfo(options)
|
||||
|
||||
**参数:**
|
||||
- `options.baseUrl` (string, 可选): API 基础 URL,默认使用 `API_BASE.APP_MEMBER`
|
||||
- `options.getToken` (Function, 可选): 获取 token 的函数
|
||||
|
||||
**返回值:**
|
||||
- `fetchUserInfo()` (Function): 获取用户信息的异步函数
|
||||
- `loading` (Ref<boolean>): 加载状态
|
||||
- `error` (Ref<Error | null>): 错误信息
|
||||
- `userInfo` (Ref<Object | null>): 用户信息数据
|
||||
|
||||
### getUserInfo(options)
|
||||
|
||||
便捷函数,直接返回用户信息对象。
|
||||
|
||||
**参数:** 同 `useUserInfo`
|
||||
|
||||
**返回值:** `Promise<Object>` 用户信息对象
|
||||
|
||||
## 🔄 在 Store 中使用
|
||||
|
||||
```javascript
|
||||
import { defineStore } from 'pinia'
|
||||
import { getUserInfo } from '@gold/hooks/web/useUserInfo'
|
||||
import { getToken } from '@/utils/token-manager'
|
||||
|
||||
export const useUserStore = defineStore('user', () => {
|
||||
const userInfo = ref(null)
|
||||
|
||||
async function fetchUserInfo() {
|
||||
try {
|
||||
const data = await getUserInfo({ getToken })
|
||||
userInfo.value = data
|
||||
} catch (error) {
|
||||
console.error('获取用户信息失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
return { userInfo, fetchUserInfo }
|
||||
})
|
||||
```
|
||||
|
||||
### useVoiceText Hook
|
||||
|
||||
语音文本转换 Hook,将音频文件转换为文本转录。
|
||||
|
||||
#### 使用方式
|
||||
|
||||
```javascript
|
||||
import useVoiceText from '@gold/hooks/web/useVoiceText'
|
||||
import type { AudioItem } from '@gold/config/types'
|
||||
|
||||
// 在组件中使用(无需任何初始化)
|
||||
const { getVoiceText } = useVoiceText()
|
||||
|
||||
const audioList: AudioItem[] = [
|
||||
{ audio_url: 'https://example.com/audio.mp3' }
|
||||
]
|
||||
|
||||
const transcriptions = await getVoiceText(audioList)
|
||||
// transcriptions: [{ key: 'url', value: 'transcribed text', audio_url: '...' }]
|
||||
```
|
||||
|
||||
#### 说明
|
||||
|
||||
`useVoiceText` Hook 直接使用 mono 级别的 `TikHubService`,无需任何初始化或配置。
|
||||
所有 API 服务都在 `@gold/api/services` 中统一管理,开箱即用。
|
||||
|
||||
#### 类型定义
|
||||
|
||||
```typescript
|
||||
import type {
|
||||
AudioItem,
|
||||
TranscriptionResult
|
||||
} from '@gold/config/types'
|
||||
```
|
||||
|
||||
## 📦 依赖
|
||||
|
||||
- `vue`: Vue 3 Composition API
|
||||
- `axios`: HTTP 请求库(用于 useUserInfo)
|
||||
- `@gold/config/api`: 公共 API 配置
|
||||
- `@gold/api/services`: Mono 级别的 API 服务
|
||||
- `@gold/api/axios/client`: Mono 级别的 Axios 客户端
|
||||
- `@gold/config/types`: 公共类型定义
|
||||
|
||||
## 🔧 配置要求
|
||||
|
||||
确保在应用的 `vite.config.js` 中配置了 `@gold` 别名:
|
||||
|
||||
```javascript
|
||||
resolve: {
|
||||
alias: {
|
||||
'@gold': fileURLToPath(new URL('../../', import.meta.url))
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -20,7 +20,7 @@ let getTokenFn = null
|
||||
* 设置获取 token 的函数
|
||||
* @param {Function} fn - 获取 token 的函数
|
||||
*/
|
||||
export function setTokenGetter(fn) {
|
||||
export function setTokensGetter(fn) {
|
||||
getTokenFn = fn
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ export function useUserInfo(options = {}) {
|
||||
|
||||
// 如果传入了 getToken 函数,设置它
|
||||
if (options.getToken) {
|
||||
setTokenGetter(options.getToken)
|
||||
setTokensGetter(options.getToken)
|
||||
}
|
||||
|
||||
// 确定 API 基础路径
|
||||
@@ -140,6 +140,10 @@ export function useUserInfo(options = {}) {
|
||||
* @returns {Promise<Object>} 用户信息对象
|
||||
*/
|
||||
export async function getUserInfo(options = {}) {
|
||||
// 如果传入了 getToken 函数,设置到全局
|
||||
if (options.getToken) {
|
||||
setTokensGetter(options.getToken)
|
||||
}
|
||||
const { fetchUserInfo } = useUserInfo(options)
|
||||
return await fetchUserInfo()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user