import axios from "axios" // 公众端专用 axios 实例 const publicApi = axios.create({ baseURL: import.meta.env.VITE_API_BASE_URL || "/api", timeout: 15000, }) // 请求拦截器 publicApi.interceptors.request.use((config) => { const token = localStorage.getItem("public_token") if (token) { config.headers.Authorization = `Bearer ${token}` } return config }) // 响应拦截器 publicApi.interceptors.response.use( (response) => { // 后端返回格式:{ code: 200, message: "success", data: xxx } // 当 data 为 null 时,直接返回 null if (response.data) { return response.data.data !== undefined ? response.data.data : response.data } return response.data }, (error) => { if (error.response?.status === 401) { localStorage.removeItem("public_token") localStorage.removeItem("public_user") // 如果在公众端页面,跳转到公众端登录 if (window.location.pathname.startsWith("/p/")) { window.location.href = "/p/login" } } return Promise.reject(error) }, ) // ==================== 认证 ==================== export interface PublicRegisterParams { username: string password: string nickname: string phone?: string city?: string } export interface PublicLoginParams { username: string password: string } export interface PublicUser { id: number username: string nickname: string phone: string | null city: string | null avatar: string | null tenantId: number tenantCode: string userSource: string userType: "adult" | "child" parentUserId: number | null roles: string[] permissions: string[] children?: any[] childrenCount?: number } export interface LoginResponse { token: string user: PublicUser } export const publicAuthApi = { register: (data: PublicRegisterParams): Promise => publicApi.post("/public/auth/register", data), login: (data: PublicLoginParams): Promise => publicApi.post("/public/auth/login", data), } // ==================== 个人信息 ==================== export const publicProfileApi = { getProfile: (): Promise => publicApi.get("/public/mine/profile"), updateProfile: (data: { nickname?: string city?: string avatar?: string gender?: string }) => publicApi.put("/public/mine/profile", data), } // ==================== 子女管理 ==================== export interface Child { id: number parentId: number name: string gender: string | null birthday: string | null grade: string | null city: string | null schoolName: string | null avatar: string | null } export interface CreateChildParams { name: string gender?: string birthday?: string grade?: string city?: string schoolName?: string } export const publicChildrenApi = { list: (): Promise => publicApi.get("/public/mine/children"), create: (data: CreateChildParams): Promise => publicApi.post("/public/mine/children", data), get: (id: number): Promise => publicApi.get(`/public/mine/children/${id}`), update: (id: number, data: Partial): Promise => publicApi.put(`/public/mine/children/${id}`, data), delete: (id: number) => publicApi.delete(`/public/mine/children/${id}`), } // ==================== 子女独立账号管理 ==================== export interface CreateChildAccountParams { username: string password: string nickname: string gender?: string birthday?: string city?: string avatar?: string relationship?: string } export interface ChildAccount { id: number username: string nickname: string avatar: string | null gender: string | null birthday: string | null city: string | null status: string userType: string createTime: string relationship: string | null controlMode: string } export const publicChildAccountApi = { // 家长为子女创建独立账号 create: (data: CreateChildAccountParams): Promise => publicApi.post("/public/children/create-account", data), // 获取子女账号列表 list: (): Promise => publicApi.get("/public/children/accounts"), // 家长切换到子女身份 switchToChild: (childUserId: number): Promise => publicApi.post("/public/auth/switch-child", { childUserId }), // 更新子女账号信息 update: (id: number, data: { nickname?: string password?: string gender?: string birthday?: string city?: string avatar?: string controlMode?: string }): Promise => publicApi.put(`/public/children/accounts/${id}`, data), // 子女查看家长信息 getParentInfo: (): Promise<{ parentId: number nickname: string avatar: string | null relationship: string | null } | null> => publicApi.get("/public/mine/parent-info"), } // ==================== 活动 ==================== export interface PublicActivity { id: number contestName: string contestType: string contestState: string status: string startTime: string endTime: string coverUrl: string | null posterUrl: string | null registerStartTime: string registerEndTime: string submitStartTime: string submitEndTime: string submitRule: string reviewStartTime: string reviewEndTime: string organizers: any visibility: string resultState: string resultPublishTime: string | null content: string address: string | null contactName: string | null contactPhone: string | null contactQrcode: string | null coOrganizers: any sponsors: any registerState: string workType: string workRequirement: string } /** 公众端活动详情(含公告、附件等扩展字段) */ export interface PublicActivityNotice { id: number title: string content: string noticeType?: string publishTime?: string createTime?: string } export interface PublicActivityAttachment { id: number fileName: string fileUrl: string fileType?: string format?: string size?: string } export interface PublicActivityDetail extends PublicActivity { /** 兼容旧字段;详情正文以后端 content 为准 */ description?: string notices?: PublicActivityNotice[] attachments?: PublicActivityAttachment[] ageMin?: number ageMax?: number targetCities?: string[] } export const publicActivitiesApi = { list: (params?: { page?: number pageSize?: number keyword?: string contestType?: string }): Promise<{ list: PublicActivity[]; total: number }> => publicApi.get("/public/activities", { params }), detail: (id: number): Promise => publicApi.get(`/public/activities/${id}`), register: ( id: number, data: { participantType: "self" | "child"; childId?: number }, ) => publicApi.post(`/public/activities/${id}/register`, data), getMyRegistration: (id: number) => publicApi.get<{ id: number contestId: number userId: number registrationType: string registrationState: string registrationTime: string hasSubmittedWork: boolean workCount: number } | null>(`/public/activities/${id}/my-registration`), submitWork: ( id: number, data: { registrationId: number userWorkId?: number title?: string description?: string files?: string[] previewUrl?: string attachments?: { fileName: string; fileUrl: string; fileType?: string; size?: string }[] }, ) => publicApi.post(`/public/activities/${id}/submit-work`, data), } // ==================== 我的报名 ==================== export const publicMineApi = { registrations: (params?: { page?: number; pageSize?: number }) => publicApi.get("/public/activities/mine/registrations", { params }), } // ==================== 点赞 & 收藏 ==================== export const publicInteractionApi = { like: (workId: number) => publicApi.post(`/public/works/${workId}/like`), favorite: (workId: number) => publicApi.post(`/public/works/${workId}/favorite`), getInteraction: (workId: number) => publicApi.get(`/public/works/${workId}/interaction`), batchStatus: (workIds: number[]) => publicApi.post("/public/works/batch-interaction", { workIds }), myFavorites: (params?: { page?: number; pageSize?: number }) => publicApi.get("/public/mine/favorites", { params }), } // ==================== 用户作品库 ==================== export interface UserWork { id: number userId: number title: string coverUrl: string | null description: string | null visibility: string status: string reviewNote: string | null originalImageUrl: string | null voiceInputUrl: string | null textInput: string | null aiMeta: any viewCount: number likeCount: number favoriteCount: number commentCount: number shareCount: number publishTime: string | null createTime: string modifyTime: string pages?: UserWorkPage[] tags?: Array<{ tag: { id: number; name: string; category: string } }> creator?: { id: number; nickname: string; avatar: string | null; username: string } _count?: { pages: number; likes: number; favorites: number; comments: number } } export interface UserWorkPage { id: number workId: number pageNo: number imageUrl: string | null text: string | null audioUrl: string | null } export const publicUserWorksApi = { // 创建作品 create: (data: { title: string coverUrl?: string description?: string visibility?: string originalImageUrl?: string voiceInputUrl?: string textInput?: string aiMeta?: any pages?: Array<{ pageNo: number; imageUrl?: string; text?: string; audioUrl?: string }> tagIds?: number[] }): Promise => publicApi.post("/public/works", data), // 我的作品列表 list: (params?: { page?: number pageSize?: number status?: string keyword?: string }): Promise<{ list: UserWork[]; total: number }> => publicApi.get("/public/works", { params }), // 作品详情 detail: (id: number): Promise => publicApi.get(`/public/works/${id}`), // 更新作品 update: (id: number, data: { title?: string description?: string coverUrl?: string visibility?: string tagIds?: number[] }): Promise => publicApi.put(`/public/works/${id}`, data), // 删除作品 delete: (id: number) => publicApi.delete(`/public/works/${id}`), // 发布作品(进入审核) publish: (id: number) => publicApi.post(`/public/works/${id}/publish`), // 获取绘本分页 getPages: (id: number): Promise => publicApi.get(`/public/works/${id}/pages`), // 保存绘本分页 savePages: (id: number, pages: Array<{ pageNo: number; imageUrl?: string; text?: string; audioUrl?: string }>) => publicApi.post(`/public/works/${id}/pages`, { pages }), } // ==================== AI 创作流程 ==================== export const publicCreationApi = { // 提交创作请求(保留但降级为辅助接口) submit: (data: { originalImageUrl: string voiceInputUrl?: string textInput?: string }): Promise<{ id: number; status: string; message: string }> => publicApi.post("/public/creation/submit", data), // 查询生成进度(返回 INT 类型 status + progress) getStatus: (id: number): Promise<{ id: number status: number progress: number progressMessage: string | null remoteWorkId: string | null title: string coverUrl: string | null }> => publicApi.get(`/public/creation/${id}/status`), // 获取生成结果(包含 pageList) getResult: (id: number): Promise => publicApi.get(`/public/creation/${id}/result`), // 创作历史 history: (params?: { page?: number; pageSize?: number }): Promise<{ list: any[]; total: number }> => publicApi.get("/public/creation/history", { params }), } // ==================== 乐读派 AI 创作集成 ==================== export const leaiApi = { // 获取乐读派创作 Token(iframe 模式主入口) getToken: (): Promise<{ token: string orgId: string h5Url: string phone: string }> => publicApi.get("/leai-auth/token"), // 刷新 Token(TOKEN_EXPIRED 时调用) refreshToken: (): Promise<{ token: string orgId: string phone: string }> => publicApi.get("/leai-auth/refresh-token"), } // ==================== 标签 ==================== export interface WorkTag { id: number name: string category: string | null usageCount: number } export const publicTagsApi = { list: (): Promise => publicApi.get("/public/tags"), hot: (): Promise => publicApi.get("/public/tags/hot"), } // ==================== 作品广场 ==================== export const publicGalleryApi = { recommended: (): Promise => publicApi.get("/public/gallery/recommended"), list: (params?: { page?: number pageSize?: number tagId?: number category?: string sortBy?: string keyword?: string }): Promise<{ list: UserWork[]; total: number }> => publicApi.get("/public/gallery", { params }), detail: (id: number): Promise => publicApi.get(`/public/gallery/${id}`), userWorks: (userId: number, params?: { page?: number; pageSize?: number }): Promise<{ list: UserWork[]; total: number }> => publicApi.get(`/public/users/${userId}/works`, { params }), } export default publicApi