This commit is contained in:
Ls
2026-04-25 17:13:25 +08:00
19 changed files with 340 additions and 646 deletions

View File

@@ -7,6 +7,7 @@
</template>
<script setup lang="ts">
// 项目根入口文件
// Nuxt4会自动注入无需手动配置
// 全局样式已移至 src/assets/css/style.css 并在 nuxt.config.ts 中全局引用
@@ -35,6 +36,7 @@ onMounted(() => {
appStore.setOnlineStatus(false)
})
}
alert("main");
})
</script>

View File

@@ -0,0 +1,120 @@
import { navigateTo } from "#app";
import { RequestExtend } from "@/extends/RequestExtend";
import { BaseConfig } from "@/config/BaseConfig";
import type { IResultData } from "@/model/common/ResultData";
type HttpMethod = "get" | "post" | "put" | "delete" | "patch";
type RequestParams = Record<string, unknown>;
export type HandledRedirectError = {
handled: true;
redirectTo: string;
message: string;
};
export class ApiService {
private static initialized = false;
private static request = new RequestExtend({
baseURL: BaseConfig.BaseUrl,
timeout: 60000
});
private static isResultData(value: unknown): value is IResultData {
return typeof value === "object" && value !== null && "code" in value && "msg" in value;
}
public static isHandledRedirectError(error: unknown): error is HandledRedirectError {
return typeof error === "object" && error !== null && "handled" in error && error.handled === true;
}
private static redirectToLogin() {
if (typeof localStorage !== "undefined") {
localStorage.removeItem("token");
localStorage.removeItem("userInfo");
}
if (typeof window !== "undefined") {
void navigateTo("/home", { replace: true });
}
}
private static ensureInitialized() {
if (this.initialized) {
return;
}
RequestExtend.addRequestInterceptor({
onFulfilled: (config) => {
const token = typeof localStorage !== "undefined" ? localStorage.getItem("token") : "";
if (token) {
config.headers = {
...config.headers,
Authorization: `Bearer ${token}`
};
}
config.timeout = 60000;
return config;
}
});
RequestExtend.addResponseInterceptor({
onFulfilled: (response) => {
if (!this.isResultData(response.data)) {
return response;
}
const result = response.data;
if (result.code === 401) {
console.log(result.data);
} else if (result.code === 40101) {
this.redirectToLogin();
throw {
handled: true,
redirectTo: "/login/login",
message: result.msg || "登录已失效"
} satisfies HandledRedirectError;
} else if (result.code === 500) {
// 跳转错误页面
} else if (result.code === 404) {
// 跳转不存在页面
}
return response;
},
onRejected: (error) => {
if (error && typeof error === "object" && "status" in error) {
// console.log("接口错误:", error);
}
return error;
}
});
this.initialized = true;
}
public static async ApiRequest<T = unknown>(
method: HttpMethod,
url: string,
params: RequestParams = {}
): Promise<IResultData<T>> {
this.ensureInitialized();
switch (method) {
case "get":
return await this.request.get<IResultData<T>>(url, { params });
case "post":
return await this.request.post<IResultData<T>>(url, params);
case "put":
return await this.request.put<IResultData<T>>(url, params);
case "delete":
return await this.request.delete<IResultData<T>>(url, { params });
case "patch":
return await this.request.patch<IResultData<T>>(url, params);
default:
throw new Error(`不支持的请求方法: ${method}`);
}
}
}

View File

@@ -0,0 +1,6 @@
/*
统一配置中心
*/
export class BaseConfig {
public static BaseUrl:string="https://localhost:7198";
}

View File

@@ -1,86 +1,87 @@
/**
* 网络请求工具类(支持实例化)
* 基于ofetch封装统一的请求逻辑支持拦截器配置
*/
export class RequestEXTEND {
type RequestConfig = {
url: string
method: string
headers: Record<string, string>
timeout?: number
body?: BodyInit | null
}
type ResponseWrapper<T = unknown> = {
data: T
status: number
statusText: string
headers: Headers
}
type RequestInterceptor = {
onFulfilled?: (config: RequestConfig) => RequestConfig | Promise<RequestConfig>
onRejected?: (error: unknown) => RequestConfig | Promise<RequestConfig>
}
type ResponseInterceptor = {
onFulfilled?: (
response: ResponseWrapper<unknown>
) => ResponseWrapper<unknown> | Promise<ResponseWrapper<unknown>>
onRejected?: (error: unknown) => unknown | Promise<unknown>
}
export class RequestExtend {
private baseURL: string
private timeout: number
private headers: Record<string, string>
// 静态默认配置
private static defaultBaseURL = ''
private static defaultTimeout = 30000
private static defaultHeaders: Record<string, string> = {
'Content-Type': 'application/json'
}
// 静态拦截器
private static requestInterceptors: Array<{
onFulfilled?: (config: any) => any
onRejected?: (error: any) => any
}> = []
private static requestInterceptors: RequestInterceptor[] = []
private static responseInterceptors: ResponseInterceptor[] = []
private static responseInterceptors: Array<{
onFulfilled?: (response: any) => any
onRejected?: (error: any) => any
}> = []
/**
* 构造函数:初始化请求配置
* @param config 自定义请求配置(可选)
*/
constructor(config?: {
baseURL?: string
timeout?: number
headers?: Record<string, string>
}) {
this.baseURL = config?.baseURL || RequestEXTEND.defaultBaseURL
this.timeout = config?.timeout || RequestEXTEND.defaultTimeout
this.baseURL = config?.baseURL || RequestExtend.defaultBaseURL
this.timeout = config?.timeout || RequestExtend.defaultTimeout
this.headers = {
...RequestEXTEND.defaultHeaders,
...RequestExtend.defaultHeaders,
...config?.headers
}
}
/**
* 设置静态默认配置
*/
static setDefaultConfig(config: {
baseURL?: string
timeout?: number
headers?: Record<string, string>
}) {
if (config.baseURL) this.defaultBaseURL = config.baseURL
if (config.timeout) this.defaultTimeout = config.timeout
if (config.headers) this.defaultHeaders = { ...this.defaultHeaders, ...config.headers }
if (config.baseURL) {
this.defaultBaseURL = config.baseURL
}
if (config.timeout) {
this.defaultTimeout = config.timeout
}
if (config.headers) {
this.defaultHeaders = { ...this.defaultHeaders, ...config.headers }
}
}
/**
* 添加请求拦截器(静态方法)
*/
static addRequestInterceptor(interceptor: {
onFulfilled?: (config: any) => any
onRejected?: (error: any) => any
}) {
static addRequestInterceptor(interceptor: RequestInterceptor) {
this.requestInterceptors.push(interceptor)
}
/**
* 添加响应拦截器(静态方法)
*/
static addResponseInterceptor(interceptor: {
onFulfilled?: (response: any) => any
onRejected?: (error: any) => any
}) {
static addResponseInterceptor(interceptor: ResponseInterceptor) {
this.responseInterceptors.push(interceptor)
}
/**
* 执行请求拦截器链
*/
private async executeRequestInterceptors(config: any): Promise<any> {
private async executeRequestInterceptors(config: RequestConfig): Promise<RequestConfig> {
let result = config
for (const interceptor of RequestEXTEND.requestInterceptors) {
for (const interceptor of RequestExtend.requestInterceptors) {
try {
if (interceptor.onFulfilled) {
result = await interceptor.onFulfilled(result)
@@ -93,81 +94,136 @@ export class RequestEXTEND {
}
}
}
return result
}
/**
* 执行响应拦截器链
*/
private async executeResponseInterceptors(response: any): Promise<any> {
private async executeResponseInterceptors(
response: ResponseWrapper<unknown>
): Promise<ResponseWrapper<unknown>> {
let result = response
for (const interceptor of RequestEXTEND.responseInterceptors) {
for (const interceptor of RequestExtend.responseInterceptors) {
try {
if (interceptor.onFulfilled) {
result = await interceptor.onFulfilled(result)
}
} catch (error) {
if (interceptor.onRejected) {
result = await interceptor.onRejected(error)
} else {
throw error
const interceptedError = await interceptor.onRejected(error)
throw interceptedError
}
throw error
}
}
return result
}
/**
* 构建请求URL
*/
private buildURL(url: string, params?: Record<string, any>): string {
private async executeResponseErrorInterceptors(error: unknown): Promise<unknown> {
let result = error
for (const interceptor of RequestExtend.responseInterceptors) {
if (!interceptor.onRejected) {
continue
}
try {
result = await interceptor.onRejected(result)
} catch (interceptorError) {
result = interceptorError
}
}
return result
}
private buildURL(url: string, params?: Record<string, unknown>): string {
let fullURL = url
// 处理相对路径
if (!url.startsWith('http://') && !url.startsWith('https://')) {
fullURL = this.baseURL + url
}
// 处理查询参数
if (params && Object.keys(params).length > 0) {
const searchParams = new URLSearchParams()
for (const key in params) {
const value = params[key]
if (value !== undefined && value !== null) {
searchParams.append(key, String(value))
}
}
const queryString = searchParams.toString()
if (queryString) {
fullURL += (fullURL.includes('?') ? '&' : '?') + queryString
}
}
return fullURL
}
/**
* 通用请求方法
*/
private async request<T = any>(
private async parseResponseBody(response: Response): Promise<unknown> {
const contentType = response.headers.get('content-type') || ''
if (contentType.includes('application/json')) {
return response.json()
}
if (contentType.includes('application/octet-stream')) {
return response.blob()
}
const text = await response.text()
if (!text) {
return text
}
try {
return JSON.parse(text)
} catch {
return text
}
}
private getErrorMessage(result: unknown, fallback: string): string {
if (typeof result === 'string' && result.trim()) {
return result
}
if (result && typeof result === 'object') {
const payload = result as { msg?: string; message?: string }
return payload.msg || payload.message || fallback
}
return fallback
}
private async request<T = unknown>(
method: string,
url: string,
options: {
params?: Record<string, any>
data?: any
params?: Record<string, unknown>
data?: unknown
headers?: Record<string, string>
} = {}
): Promise<T> {
const { params, data, headers } = options
// 构建配置
const config: any = {
const config: RequestConfig = {
method: method.toUpperCase(),
headers: {
...this.headers,
...headers
},
timeout: this.timeout
timeout: this.timeout,
url: params && method.toUpperCase() === 'GET'
? this.buildURL(url, params)
: this.buildURL(url)
}
// 添加BodyGET/HEAD请求不添加body
if (data && method.toUpperCase() !== 'GET' && method.toUpperCase() !== 'HEAD') {
if (data instanceof FormData) {
config.body = data
@@ -177,126 +233,108 @@ export class RequestEXTEND {
}
}
// 处理查询参数GET请求
if (params && method.toUpperCase() === 'GET') {
url = this.buildURL(url, params)
} else {
url = this.buildURL(url, undefined)
}
// 执行请求拦截器
config.url = url
const interceptedConfig = await this.executeRequestInterceptors(config)
try {
// 发起请求
const response = await fetch(interceptedConfig.url, {
method: interceptedConfig.method,
headers: interceptedConfig.headers,
body: interceptedConfig.body,
signal: interceptedConfig.timeout ? AbortSignal.timeout(interceptedConfig.timeout) : undefined
signal: interceptedConfig.timeout
? AbortSignal.timeout(interceptedConfig.timeout)
: undefined
})
// 处理响应
let result
const contentType = response.headers.get('content-type')
if (contentType && contentType.includes('application/json')) {
result = await response.json()
} else {
result = await response.text()
}
// 包装响应
const wrappedResponse = {
const result = await this.parseResponseBody(response)
const wrappedResponse: ResponseWrapper<unknown> = {
data: result,
status: response.status,
statusText: response.statusText,
headers: response.headers
}
// 执行响应拦截器
return await this.executeResponseInterceptors(wrappedResponse)
} catch (error: any) {
// 执行错误拦截器
const errorResponse = {
message: error.message || '网络请求失败',
code: error.code || 'NETWORK_ERROR',
status: error.status || 0
if (!response.ok) {
const handledError = await this.executeResponseErrorInterceptors({
...wrappedResponse,
message: this.getErrorMessage(result, response.statusText || 'Request failed')
})
throw handledError
}
throw errorResponse
const interceptedResponse = await this.executeResponseInterceptors(wrappedResponse)
return interceptedResponse.data as T
} catch (error) {
if (error && typeof error === 'object' && ('status' in error || 'code' in error)) {
throw error
}
const handledError = await this.executeResponseErrorInterceptors({
message: error instanceof Error ? error.message : '网络请求失败',
code:
error && typeof error === 'object' && 'code' in error
? (error as { code?: string }).code || 'NETWORK_ERROR'
: 'NETWORK_ERROR',
status:
error && typeof error === 'object' && 'status' in error
? Number((error as { status?: number }).status || 0)
: 0
})
throw handledError
}
}
/**
* GET请求
*/
async get<T = any>(url: string, options?: {
params?: Record<string, any>
async get<T = unknown>(url: string, options?: {
params?: Record<string, unknown>
headers?: Record<string, string>
}): Promise<T> {
return this.request<T>('GET', url, options)
}
/**
* POST请求
*/
async post<T = any>(url: string, data?: any, options?: {
params?: Record<string, any>
async post<T = unknown>(url: string, data?: unknown, options?: {
params?: Record<string, unknown>
headers?: Record<string, string>
}): Promise<T> {
return this.request<T>('POST', url, { ...options, data })
}
/**
* PUT请求
*/
async put<T = any>(url: string, data?: any, options?: {
params?: Record<string, any>
async put<T = unknown>(url: string, data?: unknown, options?: {
params?: Record<string, unknown>
headers?: Record<string, string>
}): Promise<T> {
return this.request<T>('PUT', url, { ...options, data })
}
/**
* DELETE请求
*/
async delete<T = any>(url: string, options?: {
params?: Record<string, any>
async delete<T = unknown>(url: string, options?: {
params?: Record<string, unknown>
headers?: Record<string, string>
}): Promise<T> {
return this.request<T>('DELETE', url, options)
}
/**
* PATCH请求
*/
async patch<T = any>(url: string, data?: any, options?: {
params?: Record<string, any>
async patch<T = unknown>(url: string, data?: unknown, options?: {
params?: Record<string, unknown>
headers?: Record<string, string>
}): Promise<T> {
return this.request<T>('PATCH', url, { ...options, data })
}
/**
* 文件上传
*/
async upload<T = any>(url: string, file: File | FormData, options?: {
params?: Record<string, any>
async upload<T = unknown>(url: string, file: File | FormData, options?: {
params?: Record<string, unknown>
headers?: Record<string, string>
}): Promise<T> {
const formData = file instanceof FormData ? file : new FormData()
if (file instanceof File) {
formData.append('file', file)
}
return this.request<T>('POST', url, {
...options,
data: formData
})
}
/**
* 文件下载
*/
async download(url: string, filename?: string): Promise<void> {
const response = await fetch(this.buildURL(url), {
method: 'GET',
@@ -318,39 +356,3 @@ export class RequestEXTEND {
window.URL.revokeObjectURL(downloadURL)
}
}
// 导出默认实例
export const request = new RequestEXTEND()
// 添加默认的Token拦截器示例
RequestEXTEND.addRequestInterceptor({
onFulfilled: (config) => {
// 从localStorage获取Token
const token = typeof localStorage !== 'undefined' ? localStorage.getItem('token') : ''
if (token) {
config.headers = {
...config.headers,
Authorization: `Bearer ${token}`
}
}
return config
}
})
// 添加默认的响应错误处理拦截器
RequestEXTEND.addResponseInterceptor({
onRejected: (error: any) => {
if (error.status === 401) {
// Token过期清除登录状态
if (typeof localStorage !== 'undefined') {
localStorage.removeItem('token')
localStorage.removeItem('userInfo')
}
// 跳转到登录页
if (typeof window !== 'undefined') {
window.location.href = '/login'
}
}
return Promise.reject(error)
}
})

View File

@@ -1,8 +1,6 @@
<template>
<slot />
<div class="footer">
</div>
</template>
<script setup lang="ts">

View File

@@ -0,0 +1,8 @@
export interface IResultData<T = unknown> {
code: number
msg: string
data?: T
ErrorData?: unknown
timestamp?: string
}

View File

@@ -7,6 +7,9 @@
definePageMeta({
layout: layout.default
})
</script>
<style scoped>

View File

@@ -0,0 +1,3 @@
<template>
ddd
</template>

View File

@@ -0,0 +1,3 @@
<template>
index
</template>

View File

@@ -0,0 +1,3 @@
<template>
test
</template>

View File

@@ -97,5 +97,10 @@ MessageExtend.notifyList('primary', ['获取装备'])
definePageMeta({
layout: layout.empty
})
showNotify({ message: '提示' });
// await navigateTo('/auth/login', { replace: true })
onMounted(() => {
req();
alert(1);
})
</script>

View File

@@ -1,209 +0,0 @@
/**
* 通用API服务
* 提供字典查询、文件上传等通用接口
*/
import type { IDictParams, IDictResponse, IUploadParams } from '~/types/api'
import type { IUploadResponse, IPageResponse, IPageParams } from '~/types/common'
import { RequestEXTEND } from '~/extends/requestEXTEND'
export class CommonSERVICE {
// 私有属性:请求工具实例
private request: RequestEXTEND
/**
* 构造函数:初始化请求工具
* @param config 自定义请求配置(可选)
*/
constructor(config?: { timeout?: number; headers?: Record<string, string>; baseURL?: string }) {
this.request = new RequestEXTEND(config)
}
/**
* 字典查询接口
* @param type 字典类型
* @returns 字典项列表
*/
async getDict(type: string): Promise<IDictResponse['data']> {
try {
const response = await this.request.get<IDictResponse>('/api/common/dict', {
params: { type }
})
if (response.code !== 200 && response.code !== 0) {
throw new Error(response.message || '获取字典失败')
}
return response.data || []
} catch (error) {
console.error('获取字典接口异常:', error)
return []
}
}
/**
* 文件上传接口
* @param file 要上传的文件
* @returns 上传后的文件信息
*/
async upload(file: File): Promise<IUploadResponse['data']> {
try {
const formData = new FormData()
formData.append('file', file)
const response = await this.request.post<IUploadResponse>('/api/common/upload', formData)
if (response.code !== 200 && response.code !== 0) {
throw new Error(response.message || '文件上传失败')
}
return response.data
} catch (error) {
console.error('文件上传接口异常:', error)
throw error
}
}
/**
* 多文件上传接口
* @param files 要上传的文件数组
* @returns 上传后的文件信息列表
*/
async uploadMultiple(files: File[]): Promise<IUploadResponse['data'][]> {
try {
const formData = new FormData()
files.forEach((file, index) => {
formData.append(`files_${index}`, file)
})
const response = await this.request.post<{ code: number; message: string; data: IUploadResponse['data'][] }>(
'/api/common/uploadMultiple',
formData
)
if (response.code !== 200 && response.code !== 0) {
throw new Error(response.message || '文件上传失败')
}
return response.data || []
} catch (error) {
console.error('多文件上传接口异常:', error)
throw error
}
}
/**
* 获取上传进度(需要自行实现)
* @param file 要上传的文件
* @param onProgress 上传进度回调
* @returns 上传后的文件信息
*/
async uploadWithProgress(
file: File,
onProgress: (percent: number) => void
): Promise<IUploadResponse['data']> {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest()
const formData = new FormData()
formData.append('file', file)
xhr.upload.addEventListener('progress', (event) => {
if (event.lengthComputable) {
const percent = Math.round((event.loaded / event.total) * 100)
onProgress(percent)
}
})
xhr.addEventListener('load', () => {
if (xhr.status >= 200 && xhr.status < 300) {
try {
const response = JSON.parse(xhr.responseText)
if (response.code === 200 || response.code === 0) {
resolve(response.data)
} else {
reject(new Error(response.message || '文件上传失败'))
}
} catch (error) {
reject(error)
}
} else {
reject(new Error('文件上传失败'))
}
})
xhr.addEventListener('error', () => {
reject(new Error('文件上传失败'))
})
xhr.open('POST', '/api/common/upload')
xhr.send(formData)
})
}
/**
* 获取配置信息
* @param key 配置键
* @returns 配置值
*/
async getConfig(key: string): Promise<string | null> {
try {
const response = await this.request.get<{ code: number; message: string; data: { value: string } }>(
'/api/common/config',
{ params: { key } }
)
if (response.code === 200 || response.code === 0) {
return response.data?.value || null
}
return null
} catch (error) {
console.error('获取配置接口异常:', error)
return null
}
}
/**
* 获取应用版本信息
* @returns 版本信息
*/
async getVersion(): Promise<{ version: string; buildTime: string }> {
try {
const response = await this.request.get<{ code: number; message: string; data: { version: string; buildTime: string } }>('/api/common/version')
if (response.code === 200 || response.code === 0) {
return response.data || { version: '1.0.0', buildTime: '' }
}
return { version: '1.0.0', buildTime: '' }
} catch (error) {
console.error('获取版本信息接口异常:', error)
return { version: '1.0.0', buildTime: '' }
}
}
/**
* 发送短信验证码
* @param phone 手机号
* @param type 验证码类型login/register/reset
* @returns 发送结果
*/
async sendSmsCode(phone: string, type: string = 'login'): Promise<boolean> {
try {
const response = await this.request.post<{ code: number; message: string }>('/api/common/sms/send', {
phone,
type
})
return response.code === 200 || response.code === 0
} catch (error) {
console.error('发送短信验证码接口异常:', error)
return false
}
}
/**
* 验证短信验证码
* @param phone 手机号
* @param code 验证码
* @returns 验证结果
*/
async verifySmsCode(phone: string, code: string): Promise<boolean> {
try {
const response = await this.request.post<{ code: number; message: string }>('/api/common/sms/verify', {
phone,
code
})
return response.code === 200 || response.code === 0
} catch (error) {
console.error('验证短信验证码接口异常:', error)
return false
}
}
}

View File

@@ -1,105 +0,0 @@
/**
* 用户相关API服务
* 提供用户登录、获取用户信息、退出登录等接口
*/
import type { ILoginParams, ILoginResponse, IGetUserInfoResponse, ILogoutResponse } from '~/types/api'
import { RequestEXTEND } from '~/extends/requestEXTEND'
export class UserSERVICE {
// 私有属性:请求工具实例
private request: RequestEXTEND
/**
* 构造函数:初始化请求工具
* @param config 自定义请求配置(可选)
*/
constructor(config?: { timeout?: number; headers?: Record<string, string>; baseURL?: string }) {
this.request = new RequestEXTEND(config)
}
/**
* 用户登录接口
* @param params 登录请求参数
* @returns 登录响应数据
*/
async login(params: ILoginParams): Promise<ILoginResponse['data']> {
try {
const response = await this.request.post<ILoginResponse>('/api/user/login', params)
if (response.code !== 200 && response.code !== 0) {
throw new Error(response.message || '登录失败')
}
return response.data
} catch (error) {
console.error('登录接口异常:', error)
throw error
}
}
/**
* 获取用户信息接口需携带Token
* @param userId 用户ID可选默认取当前登录用户ID
* @returns 用户信息
*/
async getInfo(userId?: number): Promise<IGetUserInfoResponse['data']> {
try {
const response = await this.request.get<IGetUserInfoResponse>('/api/user/info', {
params: userId ? { userId } : undefined
})
if (response.code !== 200 && response.code !== 0) {
throw new Error(response.message || '获取用户信息失败')
}
return response.data
} catch (error) {
console.error('获取用户信息接口异常:', error)
throw error
}
}
/**
* 退出登录接口
* @returns 退出结果
*/
async logout(): Promise<boolean> {
try {
const response = await this.request.post<ILogoutResponse>('/api/user/logout')
return response.code === 200 || response.code === 0
} catch (error) {
console.error('退出登录接口异常:', error)
return false
}
}
/**
* 更新用户信息
* @param data 用户信息
* @returns 更新结果
*/
async updateInfo(data: Partial<IGetUserInfoResponse['data']>): Promise<boolean> {
try {
const response = await this.request.put<ILogoutResponse>('/api/user/update', data)
return response.code === 200 || response.code === 0
} catch (error) {
console.error('更新用户信息接口异常:', error)
return false
}
}
/**
* 修改密码
* @param oldPassword 旧密码
* @param newPassword 新密码
* @returns 修改结果
*/
async changePassword(oldPassword: string, newPassword: string): Promise<boolean> {
try {
const response = await this.request.post<ILogoutResponse>('/api/user/changePassword', {
oldPassword,
newPassword
})
return response.code === 200 || response.code === 0
} catch (error) {
console.error('修改密码接口异常:', error)
return false
}
}
}

View File

@@ -1,54 +0,0 @@
/**
* API服务相关类型定义
*/
import type { IUserInfo } from './user'
import type { ICommonResponse, IPageParams, IDictItem } from './common'
// 用户登录请求参数
export type ILoginParams = {
username: string
password: string
}
// 用户登录响应体
export type ILoginResponse = ICommonResponse<{
token: string
userInfo: IUserInfo
}>
// 获取用户信息响应体
export type IGetUserInfoResponse = ICommonResponse<IUserInfo>
// 退出登录响应体
export type ILogoutResponse = ICommonResponse
// 字典查询请求参数
export type IDictParams = {
type: string
}
// 字典查询响应体
export type IDictResponse = ICommonResponse<IDictItem[]>
// 文件上传请求参数
export type IUploadParams = FormData
// 请求配置选项
export interface IRequestConfig {
timeout?: number
headers?: Record<string, string>
baseURL?: string
}
// 请求拦截器
export interface IRequestInterceptor {
onFulfilled?: (config: any) => any
onRejected?: (error: any) => any
}
// 响应拦截器
export interface IResponseInterceptor {
onFulfilled?: (response: any) => any
onRejected?: (error: any) => any
}

View File

@@ -1,63 +0,0 @@
/**
* 通用类型定义
*/
// 分页请求参数
export interface IPageParams {
page: number
pageSize: number
keyword?: string
}
// 分页响应数据
export interface IPageData<T> {
list: T[]
total: number
page: number
pageSize: number
}
// 分页响应体
export interface IPageResponse<T> {
code: number
message: string
data: IPageData<T>
}
// 通用响应体
export interface ICommonResponse<T = any> {
code: number
message: string
data?: T
}
// 字典项
export interface IDictItem {
label: string
value: string | number
}
// 字典响应
export interface IDictResponse {
code: number
message: string
data: IDictItem[]
}
// 文件上传响应
export interface IUploadResponse {
code: number
message: string
data: {
url: string
filename: string
}
}
// 文件信息
export interface IFileInfo {
name: string
url: string
size: number
type: string
}

View File

@@ -1,39 +0,0 @@
/**
* 用户相关类型定义
*/
export interface IUserInfo {
id: number
username: string
nickname: string
avatar?: string
email?: string
phone?: string
role?: string
createTime?: number
}
export interface ILoginParams {
username: string
password: string
}
export interface ILoginResponse {
code: number
message: string
data: {
token: string
userInfo: IUserInfo
}
}
export interface IGetUserInfoResponse {
code: number
message: string
data: IUserInfo
}
export interface ILogoutResponse {
code: number
message: string
}