Initial commit: 网络验证平台
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
const BASE_URL = import.meta.env.VITE_API_BASE_URL || '/api/v1'
|
||||
|
||||
const api = {
|
||||
async request<T>(endpoint: string, options: RequestInit = {}): Promise<T> {
|
||||
const token = localStorage.getItem('token')
|
||||
|
||||
const response = await fetch(`${BASE_URL}${endpoint}`, {
|
||||
...options,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
...(token && { Authorization: `Bearer ${token}` }),
|
||||
...options.headers,
|
||||
},
|
||||
})
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
if (response.status === 401 || data.code === 401) {
|
||||
localStorage.removeItem('token')
|
||||
localStorage.removeItem('user')
|
||||
window.location.href = '/login'
|
||||
throw new Error('登录已过期,请重新登录')
|
||||
}
|
||||
|
||||
if (!response.ok || data.code !== 200) {
|
||||
throw new Error(data.message || '请求失败')
|
||||
}
|
||||
|
||||
return data.data
|
||||
},
|
||||
|
||||
async get<T>(endpoint: string): Promise<T> {
|
||||
return this.request<T>(endpoint, { method: 'GET' })
|
||||
},
|
||||
|
||||
async post<T>(endpoint: string, body?: any): Promise<T> {
|
||||
return this.request<T>(endpoint, {
|
||||
method: 'POST',
|
||||
body: body ? JSON.stringify(body) : undefined,
|
||||
})
|
||||
},
|
||||
|
||||
async postFormData<T>(endpoint: string, formData: FormData): Promise<T> {
|
||||
const token = localStorage.getItem('token')
|
||||
|
||||
const response = await fetch(`${BASE_URL}${endpoint}`, {
|
||||
method: 'POST',
|
||||
body: formData,
|
||||
headers: {
|
||||
...(token && { Authorization: `Bearer ${token}` }),
|
||||
},
|
||||
})
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
if (response.status === 401 || data.code === 401) {
|
||||
localStorage.removeItem('token')
|
||||
localStorage.removeItem('user')
|
||||
window.location.href = '/login'
|
||||
throw new Error('登录已过期,请重新登录')
|
||||
}
|
||||
|
||||
if (!response.ok || data.code !== 200) {
|
||||
throw new Error(data.message || '请求失败')
|
||||
}
|
||||
|
||||
return data.data
|
||||
},
|
||||
|
||||
async put<T>(endpoint: string, body?: any): Promise<T> {
|
||||
return this.request<T>(endpoint, {
|
||||
method: 'PUT',
|
||||
body: body ? JSON.stringify(body) : undefined,
|
||||
})
|
||||
},
|
||||
|
||||
async delete<T>(endpoint: string, body?: any): Promise<T> {
|
||||
return this.request<T>(endpoint, {
|
||||
method: 'DELETE',
|
||||
body: body ? JSON.stringify(body) : undefined,
|
||||
})
|
||||
},
|
||||
}
|
||||
|
||||
export { BASE_URL }
|
||||
export default api
|
||||
@@ -0,0 +1,83 @@
|
||||
import type { AxiosError } from 'axios'
|
||||
|
||||
import { useMutation, useQuery, useQueryClient } from '@tanstack/vue-query'
|
||||
|
||||
import { useAxios } from '@/composables/use-axios'
|
||||
|
||||
import type { IResponse } from '../types/response.type'
|
||||
|
||||
export interface ITask {
|
||||
title: string
|
||||
description: string
|
||||
status: 'pending' | 'in-progress' | 'completed'
|
||||
}
|
||||
|
||||
export function useGetTasksQuery() {
|
||||
const { axiosInstance } = useAxios()
|
||||
|
||||
return useQuery<IResponse<ITask[]>, AxiosError>({
|
||||
queryKey: ['useGetTasksQuery'],
|
||||
queryFn: async () => {
|
||||
const response = await axiosInstance.get('/tasks')
|
||||
return response.data
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
export function useGetTaskByIdQuery(id: number) {
|
||||
const { axiosInstance } = useAxios()
|
||||
|
||||
return useQuery<IResponse<ITask>, AxiosError>({
|
||||
queryKey: ['useGetTaskQuery', id],
|
||||
queryFn: async () => {
|
||||
const response = await axiosInstance.get(`/tasks/${id}`)
|
||||
return response.data
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
export function useUpdateTaskMutation(id: number) {
|
||||
const { axiosInstance } = useAxios()
|
||||
const queryClient = useQueryClient()
|
||||
|
||||
return useMutation<IResponse<boolean>, AxiosError, Partial<ITask>>({
|
||||
mutationKey: ['useUpdateTaskMutation', id],
|
||||
mutationFn: async (data: Partial<ITask>) => {
|
||||
return await axiosInstance.put(`/tasks/${id}`, data)
|
||||
},
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ['useGetTaskQuery', id] })
|
||||
queryClient.invalidateQueries({ queryKey: ['useGetTasksQuery'] })
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
export function useCreateTaskMutation() {
|
||||
const { axiosInstance } = useAxios()
|
||||
const queryClient = useQueryClient()
|
||||
|
||||
return useMutation<IResponse<ITask>, AxiosError, ITask>({
|
||||
mutationKey: ['useCreateTaskMutation'],
|
||||
mutationFn: async (data: ITask) => {
|
||||
return await axiosInstance.post('/tasks', data)
|
||||
},
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ['useGetTasksQuery'] })
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
export function useDeleteTaskMutation() {
|
||||
const { axiosInstance } = useAxios()
|
||||
const queryClient = useQueryClient()
|
||||
|
||||
return useMutation<IResponse<boolean>, AxiosError, number>({
|
||||
mutationKey: ['useDeleteTaskMutation'],
|
||||
mutationFn: async (id: number) => {
|
||||
return await axiosInstance.delete(`/tasks/${id}`)
|
||||
},
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ['useGetTasksQuery'] })
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
export interface IResponse<T, E = Record<string, any>> {
|
||||
data: T
|
||||
extra: E
|
||||
code: number
|
||||
message: string
|
||||
success: boolean
|
||||
}
|
||||
|
||||
export interface IPaginationRequestQuery {
|
||||
page?: number
|
||||
pageSize?: number
|
||||
}
|
||||
|
||||
export type IRequestQuery<T extends Record<string, any>> = {
|
||||
page?: number
|
||||
pageSize?: number
|
||||
} & {
|
||||
[K in keyof T]?: T[K]
|
||||
}
|
||||
Reference in New Issue
Block a user