Initial project commit
This commit is contained in:
@@ -0,0 +1,595 @@
|
||||
import { clearAdminToken, getAdminToken, setAdminToken, setAdminUser } from './admin-auth'
|
||||
|
||||
const API_BASE
|
||||
= import.meta.env.VITE_API_BASE
|
||||
|| (import.meta.env.DEV ? 'http://127.0.0.1:8000/api/v1' : '/api/v1')
|
||||
|
||||
type RequestError = Error & { status?: number }
|
||||
|
||||
async function request<T = any>(path: string, init: RequestInit = {}) {
|
||||
const token = getAdminToken()
|
||||
const headers: Record<string, string> = {
|
||||
'Content-Type': 'application/json',
|
||||
...(init.headers as Record<string, string> || {}),
|
||||
}
|
||||
if (token)
|
||||
headers.Authorization = `Bearer ${token}`
|
||||
|
||||
let resp: Response
|
||||
try {
|
||||
resp = await fetch(`${API_BASE}${path}`, {
|
||||
...init,
|
||||
headers,
|
||||
})
|
||||
}
|
||||
catch {
|
||||
throw new Error(`接口连接失败:${API_BASE}${path}`)
|
||||
}
|
||||
|
||||
if (resp.status === 401) {
|
||||
clearAdminToken()
|
||||
throw new Error('登录已失效,请重新登录')
|
||||
}
|
||||
|
||||
const data = await resp.json().catch(() => ({}))
|
||||
if (!resp.ok) {
|
||||
const message = data?.detail || data?.message || `请求失败(${resp.status})`
|
||||
const error = new Error(message) as RequestError
|
||||
error.status = resp.status
|
||||
throw error
|
||||
}
|
||||
return data as T
|
||||
}
|
||||
|
||||
export function isRequestNotFound(error: unknown) {
|
||||
return (error as RequestError)?.status === 404
|
||||
}
|
||||
|
||||
export async function adminLogin(account: string, password: string) {
|
||||
const data = await request<{
|
||||
access_token: string
|
||||
refresh_token: string
|
||||
user: Record<string, any>
|
||||
}>('/admin/auth/login', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ account, password }),
|
||||
})
|
||||
setAdminToken(data.access_token)
|
||||
setAdminUser(data.user)
|
||||
return data
|
||||
}
|
||||
|
||||
export function adminMe() {
|
||||
return request('/admin/auth/me')
|
||||
}
|
||||
|
||||
export function adminDashboard() {
|
||||
return request('/admin/dashboard')
|
||||
}
|
||||
|
||||
export function adminModuleDesign() {
|
||||
return request('/admin/module-design')
|
||||
}
|
||||
|
||||
export function adminListUsers(params: Record<string, any>) {
|
||||
const q = new URLSearchParams()
|
||||
Object.entries(params || {}).forEach(([k, v]) => {
|
||||
if (v !== undefined && v !== null && String(v).trim() !== '')
|
||||
q.set(k, String(v))
|
||||
})
|
||||
return request(`/admin/users?${q.toString()}`)
|
||||
}
|
||||
|
||||
export function adminCreateUser(payload: Record<string, any>) {
|
||||
return request('/admin/users', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(payload),
|
||||
})
|
||||
}
|
||||
|
||||
export function adminUpdateUser(userId: number, payload: Record<string, any>) {
|
||||
return request(`/admin/users/${userId}`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(payload),
|
||||
})
|
||||
}
|
||||
|
||||
export function adminDeleteUser(userId: number) {
|
||||
return request(`/admin/users/${userId}`, {
|
||||
method: 'DELETE',
|
||||
})
|
||||
}
|
||||
|
||||
export function adminUserOptions(keyword = '') {
|
||||
const q = new URLSearchParams()
|
||||
if (keyword.trim())
|
||||
q.set('keyword', keyword.trim())
|
||||
return request(`/admin/user-options?${q.toString()}`)
|
||||
}
|
||||
|
||||
export function adminListSpots(params: Record<string, any>) {
|
||||
const q = new URLSearchParams()
|
||||
Object.entries(params || {}).forEach(([k, v]) => {
|
||||
if (v !== undefined && v !== null && String(v).trim() !== '')
|
||||
q.set(k, String(v))
|
||||
})
|
||||
return request(`/admin/spots?${q.toString()}`)
|
||||
}
|
||||
|
||||
export function adminGetSpot(spotId: number) {
|
||||
return request(`/spots/${spotId}`).then((detail: any) => ({
|
||||
id: detail.id,
|
||||
title: detail.title || '',
|
||||
city: detail.city || '',
|
||||
creator_id: detail.creator?.id || detail.creator_id || 0,
|
||||
longitude: detail.longitude ?? 0,
|
||||
latitude: detail.latitude ?? 0,
|
||||
description: detail.description || '',
|
||||
transport: detail.transport || '',
|
||||
best_time: detail.best_time || '',
|
||||
difficulty: detail.difficulty || '',
|
||||
is_free: detail.is_free ?? true,
|
||||
price_min: detail.price_min ?? null,
|
||||
price_max: detail.price_max ?? null,
|
||||
audit_status: detail.audit_status || 'pending',
|
||||
reject_reason: detail.reject_reason || '',
|
||||
tag_ids: (detail.tags || []).map((t: any) => t.id),
|
||||
image_urls: (detail.images || []).map((img: any) => img.image_url),
|
||||
images: detail.images || [],
|
||||
}))
|
||||
}
|
||||
|
||||
export function adminCreateSpot(payload: Record<string, any>) {
|
||||
return request('/admin/spots', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(payload),
|
||||
})
|
||||
}
|
||||
|
||||
export function adminUpdateSpot(spotId: number, payload: Record<string, any>) {
|
||||
return request(`/admin/spots/${spotId}`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(payload),
|
||||
})
|
||||
}
|
||||
|
||||
export function adminDeleteSpot(spotId: number) {
|
||||
return request(`/admin/spots/${spotId}`, {
|
||||
method: 'DELETE',
|
||||
})
|
||||
}
|
||||
|
||||
export function adminSpotTagOptions(keyword = '') {
|
||||
return request('/tags?sort=hot').then((items: any[]) => {
|
||||
const key = keyword.trim().toLowerCase()
|
||||
const normalized = (items || []).map((item: any) => ({
|
||||
id: item.id,
|
||||
title: item.name || item.title || '',
|
||||
}))
|
||||
if (!key)
|
||||
return normalized
|
||||
return normalized.filter(item => String(item.title).toLowerCase().includes(key))
|
||||
})
|
||||
}
|
||||
|
||||
export function adminAuditSpot(spotId: number, payload: { audit_status: string, reject_reason?: string }) {
|
||||
return request(`/admin/spots/${spotId}/audit`, {
|
||||
method: 'PATCH',
|
||||
body: JSON.stringify(payload),
|
||||
})
|
||||
}
|
||||
|
||||
export function adminBatchAuditSpots(payload: { ids: number[], audit_status: string, reject_reason?: string }) {
|
||||
return request('/admin/spots/batch-audit', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(payload),
|
||||
})
|
||||
}
|
||||
|
||||
export function adminListEvents(params: Record<string, any>) {
|
||||
const q = new URLSearchParams()
|
||||
Object.entries(params || {}).forEach(([k, v]) => {
|
||||
if (v !== undefined && v !== null && String(v).trim() !== '')
|
||||
q.set(k, String(v))
|
||||
})
|
||||
return request(`/admin/events?${q.toString()}`)
|
||||
}
|
||||
|
||||
export function adminGetEvent(eventId: number) {
|
||||
return request(`/admin/events/${eventId}`)
|
||||
}
|
||||
|
||||
export function adminCreateEvent(payload: Record<string, any>) {
|
||||
return request('/admin/events', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(payload),
|
||||
})
|
||||
}
|
||||
|
||||
export function adminUpdateEvent(eventId: number, payload: Record<string, any>) {
|
||||
return request(`/admin/events/${eventId}`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(payload),
|
||||
})
|
||||
}
|
||||
|
||||
export function adminDeleteEvent(eventId: number) {
|
||||
return request(`/admin/events/${eventId}`, {
|
||||
method: 'DELETE',
|
||||
})
|
||||
}
|
||||
|
||||
export function adminListEventRegistrations(eventId: number) {
|
||||
return request(`/admin/events/${eventId}/registrations`)
|
||||
}
|
||||
|
||||
export function adminCreateEventRegistration(eventId: number, payload: Record<string, any>) {
|
||||
return request(`/admin/events/${eventId}/registrations`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(payload),
|
||||
})
|
||||
}
|
||||
|
||||
export function adminUpdateEventRegistration(eventId: number, registrationId: number, payload: Record<string, any>) {
|
||||
return request(`/admin/events/${eventId}/registrations/${registrationId}`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(payload),
|
||||
})
|
||||
}
|
||||
|
||||
export function adminDeleteEventRegistration(eventId: number, registrationId: number) {
|
||||
return request(`/admin/events/${eventId}/registrations/${registrationId}`, {
|
||||
method: 'DELETE',
|
||||
})
|
||||
}
|
||||
|
||||
export function adminListEventPhotos(eventId: number) {
|
||||
return request(`/admin/events/${eventId}/photos`)
|
||||
}
|
||||
|
||||
export function adminCreateEventPhoto(eventId: number, payload: Record<string, any>) {
|
||||
return request(`/admin/events/${eventId}/photos`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(payload),
|
||||
})
|
||||
}
|
||||
|
||||
export function adminUpdateEventPhoto(eventId: number, photoId: number, payload: Record<string, any>) {
|
||||
return request(`/admin/events/${eventId}/photos/${photoId}`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(payload),
|
||||
})
|
||||
}
|
||||
|
||||
export function adminDeleteEventPhoto(eventId: number, photoId: number) {
|
||||
return request(`/admin/events/${eventId}/photos/${photoId}`, {
|
||||
method: 'DELETE',
|
||||
})
|
||||
}
|
||||
|
||||
export function adminAuditEvent(eventId: number, payload: { audit_status: string, reject_reason?: string }) {
|
||||
return request(`/admin/events/${eventId}/audit`, {
|
||||
method: 'PATCH',
|
||||
body: JSON.stringify(payload),
|
||||
})
|
||||
}
|
||||
|
||||
export function adminBatchAuditEvents(payload: { ids: number[], audit_status: string, reject_reason?: string }) {
|
||||
return request('/admin/events/batch-audit', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(payload),
|
||||
})
|
||||
}
|
||||
|
||||
export function adminListShooting(params: Record<string, any>) {
|
||||
const q = new URLSearchParams()
|
||||
Object.entries(params || {}).forEach(([k, v]) => {
|
||||
if (v !== undefined && v !== null && String(v).trim() !== '')
|
||||
q.set(k, String(v))
|
||||
})
|
||||
return request(`/admin/shooting?${q.toString()}`)
|
||||
}
|
||||
|
||||
export function adminGetShooting(requestId: number) {
|
||||
return request(`/admin/shooting/${requestId}`)
|
||||
}
|
||||
|
||||
export function adminCreateShooting(payload: Record<string, any>) {
|
||||
return request('/admin/shooting', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(payload),
|
||||
})
|
||||
}
|
||||
|
||||
export function adminUpdateShooting(requestId: number, payload: Record<string, any>) {
|
||||
return request(`/admin/shooting/${requestId}`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(payload),
|
||||
})
|
||||
}
|
||||
|
||||
export function adminDeleteShooting(requestId: number) {
|
||||
return request(`/admin/shooting/${requestId}`, {
|
||||
method: 'DELETE',
|
||||
})
|
||||
}
|
||||
|
||||
export function adminListShootingApplications(requestId: number) {
|
||||
return request(`/admin/shooting/${requestId}/applications`)
|
||||
}
|
||||
|
||||
export function adminCreateShootingApplication(requestId: number, payload: Record<string, any>) {
|
||||
return request(`/admin/shooting/${requestId}/applications`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(payload),
|
||||
})
|
||||
}
|
||||
|
||||
export function adminUpdateShootingApplication(requestId: number, applicationId: number, payload: Record<string, any>) {
|
||||
return request(`/admin/shooting/${requestId}/applications/${applicationId}`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(payload),
|
||||
})
|
||||
}
|
||||
|
||||
export function adminDeleteShootingApplication(requestId: number, applicationId: number) {
|
||||
return request(`/admin/shooting/${requestId}/applications/${applicationId}`, {
|
||||
method: 'DELETE',
|
||||
})
|
||||
}
|
||||
|
||||
export function adminAuditShooting(requestId: number, payload: { audit_status: string, reject_reason?: string }) {
|
||||
return request(`/admin/shooting/${requestId}/audit`, {
|
||||
method: 'PATCH',
|
||||
body: JSON.stringify(payload),
|
||||
})
|
||||
}
|
||||
|
||||
export function adminBatchAuditShooting(payload: { ids: number[], audit_status: string, reject_reason?: string }) {
|
||||
return request('/admin/shooting/batch-audit', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(payload),
|
||||
})
|
||||
}
|
||||
|
||||
export function adminListAppNavConfigs(params: Record<string, any>) {
|
||||
const q = new URLSearchParams()
|
||||
Object.entries(params || {}).forEach(([k, v]) => {
|
||||
if (v !== undefined && v !== null && String(v).trim() !== '')
|
||||
q.set(k, String(v))
|
||||
})
|
||||
return request(`/admin/app-nav-configs?${q.toString()}`)
|
||||
}
|
||||
|
||||
export function adminCreateAppNavConfig(payload: Record<string, any>) {
|
||||
return request('/admin/app-nav-configs', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(payload),
|
||||
})
|
||||
}
|
||||
|
||||
export function adminUpdateAppNavConfig(id: number, payload: Record<string, any>) {
|
||||
return request(`/admin/app-nav-configs/${id}`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(payload),
|
||||
})
|
||||
}
|
||||
|
||||
export function adminDeleteAppNavConfig(id: number) {
|
||||
return request(`/admin/app-nav-configs/${id}`, {
|
||||
method: 'DELETE',
|
||||
})
|
||||
}
|
||||
|
||||
export function adminListPromotions(params: Record<string, any>) {
|
||||
const q = new URLSearchParams()
|
||||
Object.entries(params || {}).forEach(([k, v]) => {
|
||||
if (v !== undefined && v !== null && String(v).trim() !== '')
|
||||
q.set(k, String(v))
|
||||
})
|
||||
return request(`/admin/promotions?${q.toString()}`)
|
||||
}
|
||||
|
||||
export function adminCreatePromotion(payload: Record<string, any>) {
|
||||
return request('/admin/promotions', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(payload),
|
||||
})
|
||||
}
|
||||
|
||||
export function adminUpdatePromotion(id: number, payload: Record<string, any>) {
|
||||
return request(`/admin/promotions/${id}`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(payload),
|
||||
})
|
||||
}
|
||||
|
||||
export function adminDeletePromotion(id: number) {
|
||||
return request(`/admin/promotions/${id}`, {
|
||||
method: 'DELETE',
|
||||
})
|
||||
}
|
||||
|
||||
export function adminPromotionLinkOptions(linkType: 'spot' | 'event' | 'shooting', keyword = '') {
|
||||
const q = new URLSearchParams()
|
||||
q.set('link_type', linkType)
|
||||
if (keyword.trim())
|
||||
q.set('keyword', keyword.trim())
|
||||
return request(`/admin/promotion-link-options?${q.toString()}`)
|
||||
}
|
||||
|
||||
export function adminListMembershipPlans(params: Record<string, any>) {
|
||||
const q = new URLSearchParams()
|
||||
Object.entries(params || {}).forEach(([k, v]) => {
|
||||
if (v !== undefined && v !== null && String(v).trim() !== '')
|
||||
q.set(k, String(v))
|
||||
})
|
||||
return request(`/admin/membership/plans?${q.toString()}`)
|
||||
}
|
||||
|
||||
export function adminCreateMembershipPlan(payload: Record<string, any>) {
|
||||
return request('/admin/membership/plans', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(payload),
|
||||
})
|
||||
}
|
||||
|
||||
export function adminUpdateMembershipPlan(id: number, payload: Record<string, any>) {
|
||||
return request(`/admin/membership/plans/${id}`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(payload),
|
||||
})
|
||||
}
|
||||
|
||||
export function adminDeleteMembershipPlan(id: number) {
|
||||
return request(`/admin/membership/plans/${id}`, {
|
||||
method: 'DELETE',
|
||||
})
|
||||
}
|
||||
|
||||
export function adminListUserMemberships(params: Record<string, any>) {
|
||||
const q = new URLSearchParams()
|
||||
Object.entries(params || {}).forEach(([k, v]) => {
|
||||
if (v !== undefined && v !== null && String(v).trim() !== '')
|
||||
q.set(k, String(v))
|
||||
})
|
||||
return request(`/admin/membership/user-memberships?${q.toString()}`)
|
||||
}
|
||||
|
||||
export function adminCreateUserMembership(payload: Record<string, any>) {
|
||||
return request('/admin/membership/user-memberships', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(payload),
|
||||
})
|
||||
}
|
||||
|
||||
export function adminUpdateUserMembership(id: number, payload: Record<string, any>) {
|
||||
return request(`/admin/membership/user-memberships/${id}`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(payload),
|
||||
})
|
||||
}
|
||||
|
||||
export function adminDeleteUserMembership(id: number) {
|
||||
return request(`/admin/membership/user-memberships/${id}`, {
|
||||
method: 'DELETE',
|
||||
})
|
||||
}
|
||||
|
||||
export function adminListPointLedger(params: Record<string, any>) {
|
||||
const q = new URLSearchParams()
|
||||
Object.entries(params || {}).forEach(([k, v]) => {
|
||||
if (v !== undefined && v !== null && String(v).trim() !== '')
|
||||
q.set(k, String(v))
|
||||
})
|
||||
return request(`/admin/points/ledger?${q.toString()}`)
|
||||
}
|
||||
|
||||
export function adminAdjustPoints(payload: Record<string, any>) {
|
||||
return request('/admin/points/adjust', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(payload),
|
||||
})
|
||||
}
|
||||
|
||||
export function adminRollbackPointLedger(ledgerId: number) {
|
||||
return request(`/admin/points/ledger/${ledgerId}/rollback`, {
|
||||
method: 'POST',
|
||||
})
|
||||
}
|
||||
|
||||
export function adminListNotifications(params: Record<string, any>) {
|
||||
const q = new URLSearchParams()
|
||||
Object.entries(params || {}).forEach(([k, v]) => {
|
||||
if (v !== undefined && v !== null && String(v).trim() !== '')
|
||||
q.set(k, String(v))
|
||||
})
|
||||
return request(`/admin/notifications?${q.toString()}`)
|
||||
}
|
||||
|
||||
export function adminCreateNotification(payload: Record<string, any>) {
|
||||
return request('/admin/notifications', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(payload),
|
||||
})
|
||||
}
|
||||
|
||||
export function adminUpdateNotification(id: number, payload: Record<string, any>) {
|
||||
return request(`/admin/notifications/${id}`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(payload),
|
||||
})
|
||||
}
|
||||
|
||||
export function adminDeleteNotification(id: number) {
|
||||
return request(`/admin/notifications/${id}`, {
|
||||
method: 'DELETE',
|
||||
})
|
||||
}
|
||||
|
||||
export function adminListAuditLogs(params: Record<string, any>) {
|
||||
const q = new URLSearchParams()
|
||||
Object.entries(params || {}).forEach(([k, v]) => {
|
||||
if (v !== undefined && v !== null && String(v).trim() !== '')
|
||||
q.set(k, String(v))
|
||||
})
|
||||
return request(`/admin/audit-logs?${q.toString()}`)
|
||||
}
|
||||
|
||||
export function adminCreateAuditLog(payload: Record<string, any>) {
|
||||
return request('/admin/audit-logs', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(payload),
|
||||
})
|
||||
}
|
||||
|
||||
export function adminListReports(params: Record<string, any>) {
|
||||
const q = new URLSearchParams()
|
||||
Object.entries(params || {}).forEach(([k, v]) => {
|
||||
if (v !== undefined && v !== null && String(v).trim() !== '')
|
||||
q.set(k, String(v))
|
||||
})
|
||||
return request(`/admin/reports?${q.toString()}`)
|
||||
}
|
||||
|
||||
export function adminUpdateReport(id: number, payload: Record<string, any>) {
|
||||
return request(`/admin/reports/${id}`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(payload),
|
||||
})
|
||||
}
|
||||
|
||||
export function adminDeleteReport(id: number) {
|
||||
return request(`/admin/reports/${id}`, {
|
||||
method: 'DELETE',
|
||||
})
|
||||
}
|
||||
|
||||
export function adminListSystemConfigs(params: Record<string, any>) {
|
||||
const q = new URLSearchParams()
|
||||
Object.entries(params || {}).forEach(([k, v]) => {
|
||||
if (v !== undefined && v !== null && String(v).trim() !== '')
|
||||
q.set(k, String(v))
|
||||
})
|
||||
return request(`/admin/system-configs?${q.toString()}`)
|
||||
}
|
||||
|
||||
export function adminCreateSystemConfig(payload: Record<string, any>) {
|
||||
return request('/admin/system-configs', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(payload),
|
||||
})
|
||||
}
|
||||
|
||||
export function adminUpdateSystemConfig(id: number, payload: Record<string, any>) {
|
||||
return request(`/admin/system-configs/${id}`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(payload),
|
||||
})
|
||||
}
|
||||
|
||||
export function adminDeleteSystemConfig(id: number) {
|
||||
return request(`/admin/system-configs/${id}`, {
|
||||
method: 'DELETE',
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user