import request, { type ApiEnvelope } from "@/utils/request"; export function login(username: string, password: string) { return request.post>( "/admin/v1/login", { username, password } ); } export interface AdminProfile { id: number; username: string; nickname: string; role_id: number; role_name: string; } export function fetchProfile() { return request.get>("/admin/v1/profile"); } export interface MenuNode { id: number; parent_id: number; name: string; type: number; path: string; component: string; perms: string; icon: string; sort: number; status?: number; children?: MenuNode[]; } export function fetchMyMenus() { return request.get>("/admin/v1/menus/my"); } export interface DashboardStats { pending: number; approved: number; rejected?: number; mp_users: number; wx_users: number; } export function fetchDashboardStats() { return request.get>("/admin/v1/dashboard/stats"); } export interface PendingWork { id: number; userId: number; imageUrl: string; title: string; author: string; authorOpenid: string; uploadDate: string; category: string; } export interface RejectedWork extends PendingWork { rejectReason: string; rejectDate: string; } export function fetchPendingWorks() { return request.get>("/admin/v1/works/pending"); } export function fetchRejectedWorks() { return request.get>("/admin/v1/works/rejected"); } export interface ApprovedWork extends PendingWork { order: number; /** 上传时间(完整) */ createTime?: string; /** 审核通过/上架日 */ publishDate?: string; /** 通过展示用日期(有 publish 用 publish,否则用 update) */ approvedDate?: string; updateTime?: string; } export function fetchApprovedWorks(params?: { keyword?: string }) { const keyword = params?.keyword?.trim(); return request.get>( "/admin/v1/works/approved", { params: keyword ? { keyword } : undefined } ); } export function approveWork(id: number) { return request.post(`/admin/v1/works/${id}/approve`, {}); } export function rejectWork(id: number, payload: { reason: string }) { return request.post(`/admin/v1/works/${id}/reject`, payload); } export function deleteWork(id: number) { return request.post(`/admin/v1/works/${id}/delete`, {}); } export function sortApprovedWorks(ids: number[]) { return request.post("/admin/v1/works/sort", { ids }); } export interface WorkAuditDetailImage { url: string; sort: number; } export interface WorkAuditDetailWork { id: number; userId: number; title: string; description: string; shootDate: string; status: string; coverImage: string; likesCount: number; createTime: string; categories: string[]; images: WorkAuditDetailImage[]; author: string; authorOpenid: string; authorPhone: string; rejectReason?: string; } export function fetchWorkAuditDetail(id: number) { return request.get>( `/admin/v1/works/${id}/detail` ); } export interface SysAdminRow { id: number; username: string; nickname: string; role_id: number; status: number; create_time: string; } export function fetchAdminUsers() { return request.get>("/admin/v1/users"); } export function saveAdminUser(payload: Record) { return request.post("/admin/v1/users/save", payload); } export function deleteAdminUser(id: number) { return request.post(`/admin/v1/users/${id}/delete`, {}); } export interface RoleRow { id: number; name: string; code: string; remark: string; status: number; } export function fetchRoles() { return request.get>("/admin/v1/roles"); } export function saveRole(payload: Record) { return request.post("/admin/v1/roles/save", payload); } export function deleteRole(id: number) { return request.post(`/admin/v1/roles/${id}/delete`, {}); } export function fetchRoleMenuIds(roleId: number) { return request.get>(`/admin/v1/roles/${roleId}/menus`); } export function saveRoleMenus(roleId: number, menu_ids: number[]) { return request.post(`/admin/v1/roles/${roleId}/menus`, { menu_ids }); } export function fetchMenuTree() { return request.get>("/admin/v1/menus/tree"); } export function saveMenu(payload: Record) { return request.post("/admin/v1/menus/save", payload); } export function deleteMenu(id: number) { return request.post(`/admin/v1/menus/${id}/delete`, {}); } export interface MpUserRow { id: number; phone: string; openid: string; unionid: string; nickname: string; avatar: string; bio: string; gender: number; status: number; work_count: number; create_time: string; } export function fetchMpUsers(params: { keyword?: string; page?: number; page_size?: number }) { return request.get>( "/admin/v1/mp-users", { params } ); } export function saveMpUser(payload: { id: number; nickname: string; avatar: string; bio: string; gender: number; status: number; }) { return request.post("/admin/v1/mp-users/save", payload); } export function deleteMpUser(id: number) { return request.post(`/admin/v1/mp-users/${id}/delete`, {}); } export interface BannerRow { id: number; image_url: string; title: string; subtitle: string; sort: number; status: number; create_time?: string; update_time?: string; } /** 管理后台上传图片,返回相对路径如 /uploads/20260402/xxx.png */ export function uploadAdminImage(file: File | Blob) { const fd = new FormData(); const name = file instanceof File && file.name ? file.name : file.type === "image/png" ? "upload.png" : file.type === "image/webp" ? "upload.webp" : file.type === "image/gif" ? "upload.gif" : "upload.jpg"; fd.append("file", file, name); return request.post>("/admin/v1/upload", fd); } export function fetchBanners() { return request.get>("/admin/v1/banners"); } export function saveBanner(payload: Record) { return request.post("/admin/v1/banners/save", payload); } export function deleteBanner(id: number) { return request.post(`/admin/v1/banners/${id}/delete`, {}); } export interface MapSpotRow { id: number; name: string; lat: number; lng: number; description: string; thumbnail: string; photos_count: number; pin_left_pct: number; pin_top_pct: number; sort: number; status: number; create_time?: string; update_time?: string; } export function fetchMapSpots() { return request.get>("/admin/v1/map-spots"); } export function saveMapSpot(payload: Record) { return request.post("/admin/v1/map-spots/save", payload); } export function deleteMapSpot(id: number) { return request.post(`/admin/v1/map-spots/${id}/delete`, {}); } export interface DownloadAssetsConfig { certificate: string; guide: string; updatedAt?: { certificate?: string; guide?: string; }; } export function fetchDownloadAssets() { return request.get>("/admin/v1/download-assets"); } export function saveDownloadAsset(payload: { type: "certificate" | "guide"; image_url: string }) { return request.post("/admin/v1/download-assets/save", payload); }