Initial commit: 网络验证平台

This commit is contained in:
Admin
2026-04-27 17:22:56 +08:00
commit afe67d704e
780 changed files with 88960 additions and 0 deletions
+86
View File
@@ -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]
}