import type { CleaningSettlement, CleaningTask, PageResult, SettlementStatus, TaskStatus, TransferMode, WechatTransferPreflight } from './types'; const API_BASE = (import.meta.env.VITE_ADMIN_API_BASE_URL || '/admin-api').replace(/\/$/, ''); export class ApiError extends Error { constructor( public readonly code: string, message = code, public readonly traceId = '' ) { super(message); } } export interface ApiSession { token: string; } async function request( session: ApiSession, path: string, options: RequestInit = {} ): Promise { if (!session.token.trim()) { throw new ApiError('AUTH_TOKEN_REQUIRED', '需要先填入后台访问令牌'); } const headers = new Headers(options.headers); headers.set('authorization', `Bearer ${session.token.trim()}`); if (options.body && !headers.has('content-type')) { headers.set('content-type', 'application/json'); } const response = await fetch(`${API_BASE}${path}`, { ...options, headers }); const payload = await response.json().catch(() => ({})); if (!response.ok || payload.code !== 0) { throw new ApiError( String(payload.code || `HTTP_${response.status}`), String(payload.message || '请求失败'), String(payload.traceId || '') ); } return payload.data as T; } export function listCleaningTasks( session: ApiSession, input: { page: number; pageSize: number; status?: TaskStatus } ) { const params = new URLSearchParams({ page: String(input.page), pageSize: String(input.pageSize) }); if (input.status) params.set('status', input.status); return request>(session, `/cleaning/tasks?${params}`); } export function assignCleaningTask( session: ApiSession, taskId: string, input: { cleanerUserId: string; note?: string } ) { return request(session, `/cleaning/tasks/${encodeURIComponent(taskId)}/assign`, { method: 'POST', body: JSON.stringify(input) }); } export function completeCleaningTask(session: ApiSession, taskId: string, note?: string) { return request(session, `/cleaning/tasks/${encodeURIComponent(taskId)}/complete`, { method: 'POST', body: JSON.stringify({ note }) }); } export function rejectCleaningTask(session: ApiSession, taskId: string, reason: string) { return request(session, `/cleaning/tasks/${encodeURIComponent(taskId)}/reject`, { method: 'POST', body: JSON.stringify({ reason }) }); } export function reclaimCleaningTimeouts( session: ApiSession, input: { olderThanMinutes: number; limit: number } ) { return request<{ reclaimed: number; taskIds: string[] }>(session, '/cleaning/reclaim-timeouts', { method: 'POST', body: JSON.stringify(input) }); } export function listCleaningSettlements( session: ApiSession, input: { page: number; pageSize: number; status?: SettlementStatus } ) { const params = new URLSearchParams({ page: String(input.page), pageSize: String(input.pageSize) }); if (input.status) params.set('status', input.status); return request>(session, `/cleaning/settlements?${params}`); } export function generateCleaningSettlement( session: ApiSession, input: { cleanerUserId: string; storeId?: string; note?: string } ) { return request(session, '/cleaning/settlements', { method: 'POST', body: JSON.stringify(input) }); } export function confirmCleaningSettlement(session: ApiSession, settlementId: string, note?: string) { return request( session, `/cleaning/settlements/${encodeURIComponent(settlementId)}/confirm`, { method: 'POST', body: JSON.stringify({ note }) } ); } export function executeWechatTransfer( session: ApiSession, settlementId: string, input: { mode: TransferMode; note?: string } ) { return request<{ settlement: CleaningSettlement; transferState: string; idempotent: boolean }>( session, `/cleaning/settlements/${encodeURIComponent(settlementId)}/wechat-transfer`, { method: 'POST', body: JSON.stringify(input) } ); } export function preflightWechatTransfer(session: ApiSession, settlementId: string) { return request( session, `/cleaning/settlements/${encodeURIComponent(settlementId)}/wechat-transfer/preflight` ); } export function syncWechatTransfer(session: ApiSession, settlementId: string, note?: string) { return request<{ settlement: CleaningSettlement; transferState: string; idempotent: boolean }>( session, `/cleaning/settlements/${encodeURIComponent(settlementId)}/wechat-transfer/sync`, { method: 'POST', body: JSON.stringify({ note }) } ); } export function recordPayoutFailure( session: ApiSession, settlementId: string, input: { error: string; payoutChannel?: string; payoutReference?: string; note?: string } ) { return request( session, `/cleaning/settlements/${encodeURIComponent(settlementId)}/payout-failure`, { method: 'POST', body: JSON.stringify(input) } ); }