feat: add rider h5 MVP
This commit is contained in:
45
rider-h5/src/api/http.ts
Normal file
45
rider-h5/src/api/http.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
import axios, { AxiosHeaders } from 'axios'
|
||||
|
||||
export interface ApiEnvelope<T> {
|
||||
code: number
|
||||
message: string
|
||||
data: T
|
||||
}
|
||||
|
||||
export const TOKEN_KEY = 'rider_token'
|
||||
export const USER_KEY = 'rider_user'
|
||||
|
||||
export const http = axios.create({
|
||||
baseURL: import.meta.env.VITE_API_BASE_URL || ''
|
||||
})
|
||||
|
||||
http.interceptors.request.use((config) => {
|
||||
const token = localStorage.getItem(TOKEN_KEY)
|
||||
if (token) {
|
||||
const headers = AxiosHeaders.from(config.headers)
|
||||
headers.set('satoken', token)
|
||||
headers.set('Authorization', token)
|
||||
config.headers = headers
|
||||
}
|
||||
return config
|
||||
})
|
||||
|
||||
async function unwrap<T>(request: Promise<{ data: ApiEnvelope<T> }>): Promise<T> {
|
||||
const response = await request
|
||||
if (response.data.code !== 0) {
|
||||
throw new Error(response.data.message || '请求失败')
|
||||
}
|
||||
return response.data.data
|
||||
}
|
||||
|
||||
export function apiGet<T>(url: string, params?: Record<string, unknown>) {
|
||||
return unwrap<T>(http.get(url, { params }))
|
||||
}
|
||||
|
||||
export function apiPost<T>(url: string, data?: unknown) {
|
||||
return unwrap<T>(http.post(url, data))
|
||||
}
|
||||
|
||||
export function apiPut<T>(url: string, data?: unknown) {
|
||||
return unwrap<T>(http.put(url, data))
|
||||
}
|
||||
18
rider-h5/src/api/riderTaskApi.test.ts
Normal file
18
rider-h5/src/api/riderTaskApi.test.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { groupTasksByStatus } from './riderTaskApi'
|
||||
|
||||
describe('groupTasksByStatus', () => {
|
||||
it('groups assigned delivering completed and exception tasks', () => {
|
||||
const grouped = groupTasksByStatus([
|
||||
{ id: 1, status: 'ASSIGNED' },
|
||||
{ id: 2, status: 'DELIVERING' },
|
||||
{ id: 3, status: 'DELIVERED' },
|
||||
{ id: 4, status: 'EXCEPTION' }
|
||||
])
|
||||
|
||||
expect(grouped.assigned).toHaveLength(1)
|
||||
expect(grouped.delivering).toHaveLength(1)
|
||||
expect(grouped.completed).toHaveLength(1)
|
||||
expect(grouped.exception).toHaveLength(1)
|
||||
})
|
||||
})
|
||||
58
rider-h5/src/api/riderTaskApi.ts
Normal file
58
rider-h5/src/api/riderTaskApi.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
import type { CurrentUser, DeliveryTask, FileUploadResult, RiderIncomeSummary } from '../types'
|
||||
import { apiGet, apiPost, apiPut, http } from './http'
|
||||
|
||||
export interface TaskGroups<T extends { status: string }> {
|
||||
assigned: T[]
|
||||
delivering: T[]
|
||||
completed: T[]
|
||||
exception: T[]
|
||||
canceled: T[]
|
||||
}
|
||||
|
||||
export function groupTasksByStatus<T extends { status: string }>(tasks: T[]): TaskGroups<T> {
|
||||
return {
|
||||
assigned: tasks.filter((task) => task.status === 'ASSIGNED' || task.status === 'ACCEPTED'),
|
||||
delivering: tasks.filter((task) => task.status === 'DELIVERING'),
|
||||
completed: tasks.filter((task) => task.status === 'DELIVERED' || task.status === 'COMPLETED'),
|
||||
exception: tasks.filter((task) => task.status === 'EXCEPTION'),
|
||||
canceled: tasks.filter((task) => task.status === 'CANCELED')
|
||||
}
|
||||
}
|
||||
|
||||
export function riderLogin(username: string, password: string) {
|
||||
return apiPost<CurrentUser>('/api/auth/admin-login', { username, password })
|
||||
}
|
||||
|
||||
export function listRiderTasks() {
|
||||
return apiGet<DeliveryTask[]>('/api/rider/tasks')
|
||||
}
|
||||
|
||||
export function getRiderTask(id: number) {
|
||||
return apiGet<DeliveryTask>(`/api/rider/tasks/${id}`)
|
||||
}
|
||||
|
||||
export function startRiderTask(id: number) {
|
||||
return apiPut<DeliveryTask>(`/api/rider/tasks/${id}/start`)
|
||||
}
|
||||
|
||||
export function deliverRiderTask(id: number, photoUrl?: string) {
|
||||
return apiPut<DeliveryTask>(`/api/rider/tasks/${id}/delivered`, { photoUrl })
|
||||
}
|
||||
|
||||
export function markRiderTaskException(id: number, exceptionType: string, exceptionNote: string) {
|
||||
return apiPut<DeliveryTask>(`/api/rider/tasks/${id}/exception`, { exceptionType, exceptionNote })
|
||||
}
|
||||
|
||||
export function getIncomeSummary() {
|
||||
return apiGet<RiderIncomeSummary>('/api/rider/income-summary')
|
||||
}
|
||||
|
||||
export async function uploadDeliveredPhoto(file: File) {
|
||||
const data = new FormData()
|
||||
data.append('file', file)
|
||||
const response = await http.post<{ code: number; message: string; data: FileUploadResult }>('/api/files/upload', data)
|
||||
if (response.data.code !== 0) {
|
||||
throw new Error(response.data.message || '上传失败')
|
||||
}
|
||||
return response.data.data
|
||||
}
|
||||
Reference in New Issue
Block a user