189 lines
4.4 KiB
TypeScript
189 lines
4.4 KiB
TypeScript
// 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 }
|