Files
mini-yu/utils/api.ts

189 lines
4.4 KiB
TypeScript
Raw Normal View History

2026-02-10 08:05:03 +08:00
// API 基础配置
const BASE_URL = 'https://api.makesong.cn/yu'
// 响应数据类型
interface ApiResponse<T = any> {
code: number
message: string
data: T
}
// 用户类型
interface User {
id: number
phone: string
nickname: string
role: string
created_at?: string
}
// 登录响应
interface LoginResponse {
token: string
user: User
}
// 时间槽类型
interface TimeSlot {
id: number
date: string
start_time: string
end_time: string
max_people: number
current_people: number
is_active: boolean
}
// 预约类型
interface Appointment {
id: number
user_id: number
time_slot_id: number
people_count: number
status: 'pending' | 'confirmed' | 'cancelled' | 'completed'
notes: string
created_at: string
user?: User
time_slot?: TimeSlot
}
// HTTP 请求方法
function request<T>(url: string, options: UniApp.RequestOptions = {}): Promise<T> {
// 从本地存储获取 token
const token = uni.getStorageSync('token')
// 对于 GET 请求,将查询参数拼接到 URL 中
let requestUrl = BASE_URL + url
if ((options.method || 'GET') === 'GET' && options.data) {
const params: string[] = []
Object.keys(options.data).forEach(key => {
const value = options.data[key]
if (value !== undefined && value !== null) {
params.push(`${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`)
}
})
const queryString = params.join('&')
if (queryString) {
requestUrl += '?' + queryString
}
}
return new Promise((resolve, reject) => {
uni.request({
url: requestUrl,
method: options.method || 'GET',
data: (options.method || 'GET') === 'GET' ? undefined : options.data,
header: {
'Content-Type': 'application/json',
...(token && { Authorization: `Bearer ${token}` }),
...options.header,
},
success: (res: any) => {
const data = res.data as ApiResponse<T>
if (data.code === 200) {
resolve(data.data)
}else if(data.code == 401){
uni.removeStorageSync('token');
uni.reLaunch({
url: '/pages/login/login'
})
} else {
uni.showToast({
title: data.message || '请求失败',
icon: 'none'
})
reject(new Error(data.message))
}
},
fail: (err) => {
uni.showToast({
title: '网络请求失败',
icon: 'none'
})
reject(err)
}
})
})
}
// API 方法
export const api = {
// 认证相关
auth: {
register: (phone: string, nickname: string) =>
request<LoginResponse>('/api/auth/register', {
method: 'POST',
data: { phone, nickname }
}),
sendCode: (phone: string) =>
request<{ message: string; expires_in: number }>('/api/auth/send-code', {
method: 'POST',
data: { phone }
}),
verificationLogin: (phone: string, code: string) =>
request<LoginResponse>('/api/auth/verification-login', {
method: 'POST',
data: { phone, code }
}),
oneClickLogin: (phone: string) =>
request<LoginResponse>('/api/auth/one-click-login', {
method: 'POST',
data: { phone }
})
},
// 用户相关
user: {
getProfile: () =>
request<User>('/api/users/profile'),
updateProfile: (data: Partial<User>) =>
request<User>('/api/users/profile', {
method: 'PUT',
data
})
},
// 时间槽相关
timeslots: {
getList: (params?: { date?: string; is_active?: boolean }) =>
request<TimeSlot[]>('/api/timeslots', {
data: params
}),
getById: (id: number) =>
request<TimeSlot>(`/api/timeslots/${id}`)
},
// 预约相关
appointments: {
getList: (params?: { status?: string; date?: string }) =>
request<Appointment[]>('/api/appointments', {
data: params
}),
getById: (id: number) =>
request<Appointment>(`/api/appointments/${id}`),
create: (time_slot_id: number, people_count: number = 1, notes?: string) =>
request<Appointment>('/api/appointments', {
method: 'POST',
data: { time_slot_id, people_count, notes }
}),
cancel: (id: number) =>
request<Appointment>(`/api/appointments/${id}`, {
method: 'DELETE'
})
},
// 健康检查
health: () =>
request<{ status: string }>('/health')
}
export type { User, TimeSlot, Appointment, ApiResponse }