mirror of
https://github.com/allinssl/allinssl.git
synced 2025-12-21 10:14:03 +08:00
【同步】前端项目源码
【修复】工作流兼容问题
This commit is contained in:
284
frontend/packages/vue/hooks/docs/useAxios.md
Normal file
284
frontend/packages/vue/hooks/docs/useAxios.md
Normal file
@@ -0,0 +1,284 @@
|
||||
# useAxios 使用文档
|
||||
|
||||
## 基本介绍
|
||||
|
||||
`useAxios` 是一个基于 Vue 3 的 Axios 封装钩子函数,它提供了一种简洁的方式来管理 HTTP 请求。通过这个钩子函数,你可以轻松地处理请求状态、加载状态、错误处理、请求取消等功能。
|
||||
|
||||
## 核心函数
|
||||
|
||||
### useAxios
|
||||
|
||||
```typescript
|
||||
function useAxios<T = unknown, Z = Record<string, unknown>>(instance: HttpClient): useAxiosReturn<T, Z>
|
||||
```
|
||||
|
||||
**参数**:
|
||||
|
||||
- `instance`: HttpClient 实例,用于发送 HTTP 请求
|
||||
|
||||
**返回值**:
|
||||
包含以下属性和方法的对象:
|
||||
|
||||
**状态属性**:
|
||||
|
||||
- `loadingMask`: 加载遮罩配置,类型为 `Ref<{ status: boolean } & LoadingMaskOptions>`
|
||||
- `message`: 是否显示响应消息,类型为 `Ref<boolean>`
|
||||
- `dialog`: 确认框配置,类型为 `Ref<{ status: boolean } & CustomDialogOptions>`
|
||||
- `loading`: 是否正在加载,类型为 `Ref<boolean>`
|
||||
- `error`: 错误信息,类型为 `ShallowRef<Error | null | string>`
|
||||
- `response`: 原始响应对象,类型为 `ShallowRef<AxiosResponse<T> | null>`
|
||||
- `data`: 响应数据,类型为 `Ref<T>`
|
||||
- `defaultData`: 默认数据,类型为 `Ref<T>`
|
||||
- `statusCode`: HTTP 状态码,类型为 `ComputedRef<HttpStatusCode | null>`
|
||||
- `aborted`: 是否被中断,类型为 `Ref<boolean>`
|
||||
- `urlRef`: 请求 URL,类型为 `Ref<string>`
|
||||
- `paramsRef`: 请求参数,类型为 `Ref<Z>`
|
||||
|
||||
**方法**:
|
||||
|
||||
- `execute(url: string, params?: Z)`: 执行请求,返回 `Promise<T>`
|
||||
- `setParams(params: Z)`: 设置请求参数并执行请求,返回 `Promise<T>`
|
||||
- `setUrl(url: string, params?: Z)`: 设置请求 URL 和参数并执行请求,返回 `Promise<T>`
|
||||
- `cancel(url: string)`: 取消特定请求
|
||||
- `cancelAll()`: 取消所有请求
|
||||
- `start(params?: Z)`: 使用当前 URL 和参数重新发起请求,返回 `Promise<T>`
|
||||
|
||||
## 使用示例
|
||||
|
||||
### 基本用法
|
||||
|
||||
```typescript
|
||||
import { useAxios, HttpClient } from '@baota/hooks/axios'
|
||||
|
||||
// 创建 HTTP 客户端实例
|
||||
const httpClient = new HttpClient({
|
||||
baseURL: 'https://api.example.com',
|
||||
})
|
||||
|
||||
// 创建请求钩子
|
||||
const api = useAxios<UserData, UserParams>(httpClient)
|
||||
|
||||
// 发送请求
|
||||
const fetchUser = async (userId: string) => {
|
||||
try {
|
||||
const result = await api.execute('/user/info', { userId })
|
||||
console.log('用户数据:', result)
|
||||
return result
|
||||
} catch (error) {
|
||||
console.error('获取用户数据失败:', error)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 配置加载遮罩
|
||||
|
||||
```typescript
|
||||
import { useAxios, HttpClient } from '@baota/hooks/axios'
|
||||
|
||||
const httpClient = new HttpClient({
|
||||
baseURL: 'https://api.example.com',
|
||||
})
|
||||
|
||||
const api = useAxios(httpClient)
|
||||
|
||||
// 配置加载遮罩
|
||||
api.loadingMask.value = {
|
||||
status: true, // 启用加载遮罩
|
||||
text: '正在加载数据,请稍候...', // 自定义加载文本
|
||||
}
|
||||
|
||||
// 发送请求时会自动显示加载遮罩
|
||||
api.execute('/data/list', { page: 1 })
|
||||
```
|
||||
|
||||
### 配置确认对话框
|
||||
|
||||
```typescript
|
||||
import { useAxios, HttpClient } from '@baota/hooks/axios'
|
||||
|
||||
const httpClient = new HttpClient({
|
||||
baseURL: 'https://api.example.com',
|
||||
})
|
||||
|
||||
const api = useAxios(httpClient)
|
||||
|
||||
// 配置确认对话框
|
||||
api.dialog.value = {
|
||||
status: true, // 启用确认对话框
|
||||
title: '确认操作',
|
||||
content: '确定要执行此操作吗?',
|
||||
positiveText: '确定',
|
||||
negativeText: '取消',
|
||||
}
|
||||
|
||||
// 发送请求前会先显示确认对话框
|
||||
api.execute('/user/delete', { userId: '123' })
|
||||
```
|
||||
|
||||
### 启用响应消息提示
|
||||
|
||||
```typescript
|
||||
import { useAxios, HttpClient } from '@baota/hooks/axios'
|
||||
|
||||
const httpClient = new HttpClient({
|
||||
baseURL: 'https://api.example.com',
|
||||
})
|
||||
|
||||
const api = useAxios(httpClient)
|
||||
|
||||
// 启用响应消息提示
|
||||
api.message.value = true
|
||||
|
||||
// 发送请求后会自动显示响应中的消息
|
||||
// 假设响应格式为 { status: boolean, message: string, data: any }
|
||||
api.execute('/user/update', { userId: '123', name: '张三' })
|
||||
```
|
||||
|
||||
### 取消请求
|
||||
|
||||
```typescript
|
||||
import { useAxios, HttpClient } from '@baota/hooks/axios'
|
||||
|
||||
const httpClient = new HttpClient({
|
||||
baseURL: 'https://api.example.com',
|
||||
})
|
||||
|
||||
const api = useAxios(httpClient)
|
||||
|
||||
// 发送请求
|
||||
const fetchData = () => {
|
||||
api.execute('/data/large-file')
|
||||
}
|
||||
|
||||
// 取消特定请求
|
||||
const cancelFetch = () => {
|
||||
api.cancel('/data/large-file')
|
||||
}
|
||||
|
||||
// 取消所有请求
|
||||
const cancelAllRequests = () => {
|
||||
api.cancelAll()
|
||||
}
|
||||
```
|
||||
|
||||
### 重新发送请求
|
||||
|
||||
```typescript
|
||||
import { useAxios, HttpClient } from '@baota/hooks/axios'
|
||||
|
||||
const httpClient = new HttpClient({
|
||||
baseURL: 'https://api.example.com',
|
||||
})
|
||||
|
||||
const api = useAxios(httpClient)
|
||||
|
||||
// 首次发送请求
|
||||
api.execute('/data/list', { page: 1 })
|
||||
|
||||
// 更新参数并重新发送请求
|
||||
const nextPage = () => {
|
||||
api.setParams({ page: api.paramsRef.value.page + 1 })
|
||||
}
|
||||
|
||||
// 使用当前参数重新发送请求
|
||||
const refresh = () => {
|
||||
api.start()
|
||||
}
|
||||
```
|
||||
|
||||
### 监听请求状态
|
||||
|
||||
```typescript
|
||||
import { useAxios, HttpClient } from '@baota/hooks/axios'
|
||||
import { watch } from 'vue'
|
||||
|
||||
const httpClient = new HttpClient({
|
||||
baseURL: 'https://api.example.com',
|
||||
})
|
||||
|
||||
const api = useAxios(httpClient)
|
||||
|
||||
// 监听加载状态
|
||||
watch(api.loading, (isLoading) => {
|
||||
console.log('加载状态:', isLoading)
|
||||
})
|
||||
|
||||
// 监听错误状态
|
||||
watch(api.error, (error) => {
|
||||
if (error) {
|
||||
console.error('请求错误:', error)
|
||||
}
|
||||
})
|
||||
|
||||
// 监听响应数据
|
||||
watch(api.data, (data) => {
|
||||
console.log('响应数据:', data)
|
||||
})
|
||||
```
|
||||
|
||||
## 高级用法
|
||||
|
||||
### 设置默认数据
|
||||
|
||||
```typescript
|
||||
import { useAxios, HttpClient } from '@baota/hooks/axios'
|
||||
|
||||
const httpClient = new HttpClient({
|
||||
baseURL: 'https://api.example.com',
|
||||
})
|
||||
|
||||
const api = useAxios<{ list: any[]; total: number }>(httpClient)
|
||||
|
||||
// 设置默认数据
|
||||
api.defaultData.value = { list: [], total: 0 }
|
||||
|
||||
// 当请求失败时,data 会被重置为默认数据
|
||||
api.execute('/data/list', { page: 1 })
|
||||
```
|
||||
|
||||
### 类型化请求和响应
|
||||
|
||||
```typescript
|
||||
import { useAxios, HttpClient } from '@baota/hooks/axios'
|
||||
|
||||
// 定义响应数据类型
|
||||
interface UserData {
|
||||
id: string
|
||||
name: string
|
||||
email: string
|
||||
role: string
|
||||
}
|
||||
|
||||
// 定义请求参数类型
|
||||
interface UserParams {
|
||||
userId: string
|
||||
}
|
||||
|
||||
const httpClient = new HttpClient({
|
||||
baseURL: 'https://api.example.com',
|
||||
})
|
||||
|
||||
// 创建类型化的请求钩子
|
||||
const api = useAxios<UserData, UserParams>(httpClient)
|
||||
|
||||
// 发送类型化的请求
|
||||
const fetchUser = async (userId: string) => {
|
||||
const user = await api.execute('/user/info', { userId })
|
||||
// user 的类型为 UserData
|
||||
console.log(`用户名: ${user.name}, 角色: ${user.role}`)
|
||||
}
|
||||
```
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. `useAxios` 默认使用 POST 方法发送请求,如需使用其他 HTTP 方法,需要在 HttpClient 实例中配置。
|
||||
|
||||
2. 响应消息提示功能要求响应数据格式包含 `status` 和 `message` 字段。
|
||||
|
||||
3. 加载遮罩、确认对话框和响应消息提示功能依赖于 `@baota/naive-ui/hooks` 提供的相关组件。
|
||||
|
||||
4. 取消请求功能基于 Axios 的 AbortController 实现,可以通过 URL 来标识和取消特定请求。
|
||||
|
||||
5. 当请求被取消时,`aborted` 状态会被设置为 `true`,可以通过监听此状态来处理请求取消的情况。
|
||||
|
||||
6. 错误处理会自动显示错误消息,并将错误信息存储在 `error` 状态中。
|
||||
332
frontend/packages/vue/hooks/docs/useSocket.md
Normal file
332
frontend/packages/vue/hooks/docs/useSocket.md
Normal file
@@ -0,0 +1,332 @@
|
||||
# useSocket 使用文档
|
||||
|
||||
## 基本介绍
|
||||
|
||||
`useSocket` 是一个基于 Vue 3 的 WebSocket 封装钩子函数,它提供了一种简洁的方式来管理 WebSocket 连接。通过这个钩子函数,你可以轻松地处理连接状态、消息收发、自动重连、心跳机制等功能。
|
||||
|
||||
## 核心函数
|
||||
|
||||
### useSocket
|
||||
|
||||
```typescript
|
||||
function useSocket(url: string, options?: SocketOptions): UseSocketReturn
|
||||
```
|
||||
|
||||
**参数**:
|
||||
|
||||
- `url`: 字符串类型,WebSocket 服务器的 URL
|
||||
- `options`: 可选的 SocketOptions 配置对象
|
||||
|
||||
**SocketOptions 选项**:
|
||||
|
||||
```typescript
|
||||
interface SocketOptions {
|
||||
autoReconnect?: boolean; // 是否自动重连, 默认为 true
|
||||
middleware?: (data: any) => any; // 数据中间件函数,支持原始数据处理,默认为直接返回
|
||||
maxReconnectAttempts?: number; // 最大重连次数, 默认无限制
|
||||
reconnectDelay?: number; // 重连延迟, 默认为3000ms
|
||||
heartbeatInterval?: number; // 心跳间隔, 单位毫秒, 默认为5000ms
|
||||
heartbeatMessage?: any; // 心跳包消息, 默认为 'ping'
|
||||
}
|
||||
```
|
||||
|
||||
**返回值**:
|
||||
包含以下属性和方法的对象:
|
||||
|
||||
**状态属性**:
|
||||
|
||||
- `socket`: WebSocket 实例,类型为 `Ref<WebSocket | null>`
|
||||
- `connected`: 连接状态,类型为 `Ref<boolean>`
|
||||
- `message`: 接收到的消息,类型为 `Ref<any>`
|
||||
|
||||
**方法**:
|
||||
|
||||
- `connect()`: 建立 WebSocket 连接
|
||||
- `disconnect()`: 主动断开连接,禁止自动重连
|
||||
- `send(data: any)`: 发送数据,仅在连接状态时执行
|
||||
|
||||
## 使用示例
|
||||
|
||||
### 基本用法
|
||||
|
||||
```typescript
|
||||
import { useSocket } from '@baota/hooks/socket'
|
||||
|
||||
// 创建 WebSocket 钩子
|
||||
const { socket, connect, disconnect, send, message, connected } = useSocket('wss://example.com/ws')
|
||||
|
||||
// 建立连接
|
||||
connect()
|
||||
|
||||
// 监听连接状态
|
||||
watch(connected, (isConnected) => {
|
||||
if (isConnected) {
|
||||
console.log('WebSocket已连接')
|
||||
} else {
|
||||
console.log('WebSocket已断开')
|
||||
}
|
||||
})
|
||||
|
||||
// 监听接收到的消息
|
||||
watch(message, (newMessage) => {
|
||||
if (newMessage) {
|
||||
console.log('收到消息:', newMessage)
|
||||
}
|
||||
})
|
||||
|
||||
// 发送消息
|
||||
const sendMessage = () => {
|
||||
send(JSON.stringify({ type: 'greeting', content: '你好,服务器!' }))
|
||||
}
|
||||
|
||||
// 断开连接
|
||||
const closeConnection = () => {
|
||||
disconnect()
|
||||
}
|
||||
```
|
||||
|
||||
### 配置自动重连
|
||||
|
||||
```typescript
|
||||
import { useSocket } from '@baota/hooks/socket'
|
||||
|
||||
// 配置自动重连
|
||||
const { connect, disconnect } = useSocket('wss://example.com/ws', {
|
||||
autoReconnect: true, // 启用自动重连
|
||||
maxReconnectAttempts: 5, // 最多重连5次
|
||||
reconnectDelay: 2000 // 2秒后重连
|
||||
})
|
||||
|
||||
// 建立连接
|
||||
connect()
|
||||
```
|
||||
|
||||
### 使用数据中间件
|
||||
|
||||
```typescript
|
||||
import { useSocket } from '@baota/hooks/socket'
|
||||
|
||||
// 配置数据中间件,自动解析JSON
|
||||
const { connect, message } = useSocket('wss://example.com/ws', {
|
||||
middleware: (data) => {
|
||||
try {
|
||||
return JSON.parse(data)
|
||||
} catch (e) {
|
||||
return data
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// 建立连接
|
||||
connect()
|
||||
|
||||
// 此时接收到的消息已经被解析为JSON对象
|
||||
watch(message, (newMessage) => {
|
||||
if (newMessage) {
|
||||
console.log('消息类型:', newMessage.type)
|
||||
console.log('消息内容:', newMessage.content)
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
### 配置心跳机制
|
||||
|
||||
```typescript
|
||||
import { useSocket } from '@baota/hooks/socket'
|
||||
|
||||
// 配置心跳机制
|
||||
const { connect } = useSocket('wss://example.com/ws', {
|
||||
heartbeatInterval: 10000, // 10秒发送一次心跳
|
||||
heartbeatMessage: JSON.stringify({ type: 'heartbeat' }) // 自定义心跳消息
|
||||
})
|
||||
|
||||
// 建立连接,会自动启动心跳
|
||||
connect()
|
||||
```
|
||||
|
||||
### 与后端服务集成
|
||||
|
||||
```typescript
|
||||
import { useSocket } from '@baota/hooks/socket'
|
||||
import { ref } from 'vue'
|
||||
|
||||
// 创建聊天应用示例
|
||||
const chatMessages = ref<{ sender: string; content: string }[]>([])
|
||||
const newMessage = ref('')
|
||||
|
||||
const { connect, send, message, connected } = useSocket('wss://chat.example.com/ws', {
|
||||
middleware: (data) => JSON.parse(data)
|
||||
})
|
||||
|
||||
// 连接到聊天服务器
|
||||
connect()
|
||||
|
||||
// 监听新消息
|
||||
watch(message, (msg) => {
|
||||
if (msg && msg.type === 'chat') {
|
||||
chatMessages.value.push({
|
||||
sender: msg.sender,
|
||||
content: msg.content
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
// 发送新消息
|
||||
const sendChatMessage = () => {
|
||||
if (newMessage.value.trim() && connected.value) {
|
||||
send(JSON.stringify({
|
||||
type: 'chat',
|
||||
content: newMessage.value
|
||||
}))
|
||||
newMessage.value = ''
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 在组件卸载时断开连接
|
||||
|
||||
```typescript
|
||||
import { useSocket } from '@baota/hooks/socket'
|
||||
import { onUnmounted } from 'vue'
|
||||
|
||||
export default {
|
||||
setup() {
|
||||
const { connect, disconnect, send, message, connected } = useSocket('wss://example.com/ws')
|
||||
|
||||
// 建立连接
|
||||
connect()
|
||||
|
||||
// 在组件卸载时断开连接
|
||||
onUnmounted(() => {
|
||||
disconnect()
|
||||
})
|
||||
|
||||
return { send, message, connected }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 高级用法
|
||||
|
||||
### 结合 TypeScript 类型定义
|
||||
|
||||
```typescript
|
||||
import { useSocket } from '@baota/hooks/socket'
|
||||
import { ref, watch } from 'vue'
|
||||
|
||||
// 定义消息类型
|
||||
interface ServerMessage {
|
||||
type: 'chat' | 'notification' | 'system';
|
||||
timestamp: number;
|
||||
content: string;
|
||||
sender?: string;
|
||||
}
|
||||
|
||||
// 创建带类型的消息引用
|
||||
const typedMessage = ref<ServerMessage | null>(null)
|
||||
|
||||
const { connect, message } = useSocket('wss://example.com/ws', {
|
||||
middleware: (data) => {
|
||||
try {
|
||||
return JSON.parse(data) as ServerMessage
|
||||
} catch (e) {
|
||||
console.error('消息解析失败:', e)
|
||||
return null
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
connect()
|
||||
|
||||
// 监听并处理不同类型的消息
|
||||
watch(message, (newMessage) => {
|
||||
if (newMessage) {
|
||||
typedMessage.value = newMessage
|
||||
|
||||
switch (newMessage.type) {
|
||||
case 'chat':
|
||||
console.log(`[${newMessage.sender}]: ${newMessage.content}`)
|
||||
break
|
||||
case 'notification':
|
||||
console.log(`通知: ${newMessage.content}`)
|
||||
break
|
||||
case 'system':
|
||||
console.log(`系统消息: ${newMessage.content}`)
|
||||
break
|
||||
}
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
### 处理多个 WebSocket 连接
|
||||
|
||||
```typescript
|
||||
import { useSocket } from '@baota/hooks/socket'
|
||||
|
||||
// 创建多个 WebSocket 连接
|
||||
const chatSocket = useSocket('wss://chat.example.com/ws')
|
||||
const notificationSocket = useSocket('wss://notification.example.com/ws')
|
||||
const dataStreamSocket = useSocket('wss://datastream.example.com/ws')
|
||||
|
||||
// 分别连接
|
||||
chatSocket.connect()
|
||||
notificationSocket.connect()
|
||||
dataStreamSocket.connect()
|
||||
|
||||
// 监听不同连接的消息
|
||||
watch(chatSocket.message, (msg) => {
|
||||
console.log('聊天消息:', msg)
|
||||
})
|
||||
|
||||
watch(notificationSocket.message, (msg) => {
|
||||
console.log('通知消息:', msg)
|
||||
})
|
||||
|
||||
watch(dataStreamSocket.message, (msg) => {
|
||||
console.log('数据流消息:', msg)
|
||||
})
|
||||
|
||||
// 发送不同类型的消息
|
||||
const sendChatMessage = (content) => {
|
||||
chatSocket.send(JSON.stringify({ type: 'chat', content }))
|
||||
}
|
||||
|
||||
const sendCommand = (command) => {
|
||||
dataStreamSocket.send(JSON.stringify({ type: 'command', command }))
|
||||
}
|
||||
```
|
||||
|
||||
### 实现可视化的连接状态
|
||||
|
||||
```typescript
|
||||
import { useSocket } from '@baota/hooks/socket'
|
||||
import { computed } from 'vue'
|
||||
|
||||
const { connect, disconnect, connected } = useSocket('wss://example.com/ws')
|
||||
|
||||
// 计算连接状态的显示文本和样式
|
||||
const connectionStatus = computed(() => {
|
||||
return connected.value ? '已连接' : '未连接'
|
||||
})
|
||||
|
||||
const statusClass = computed(() => {
|
||||
return {
|
||||
'status-connected': connected.value,
|
||||
'status-disconnected': !connected.value
|
||||
}
|
||||
})
|
||||
|
||||
// 连接按钮的状态
|
||||
const connectButtonText = computed(() => {
|
||||
return connected.value ? '断开连接' : '建立连接'
|
||||
})
|
||||
|
||||
// 切换连接状态的方法
|
||||
const toggleConnection = () => {
|
||||
if (connected.value) {
|
||||
disconnect()
|
||||
} else {
|
||||
connect()
|
||||
}
|
||||
}
|
||||
```
|
||||
Reference in New Issue
Block a user