2026-03-27 22:20:25 +08:00
|
|
|
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) => response.data?.data ?? 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<LoginResponse> =>
|
|
|
|
|
publicApi.post("/public/auth/register", data),
|
|
|
|
|
|
|
|
|
|
login: (data: PublicLoginParams): Promise<LoginResponse> =>
|
|
|
|
|
publicApi.post("/public/auth/login", data),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ==================== 个人信息 ====================
|
|
|
|
|
|
|
|
|
|
export const publicProfileApi = {
|
|
|
|
|
getProfile: (): Promise<PublicUser> => 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<Child[]> => publicApi.get("/public/mine/children"),
|
|
|
|
|
|
|
|
|
|
create: (data: CreateChildParams): Promise<Child> =>
|
|
|
|
|
publicApi.post("/public/mine/children", data),
|
|
|
|
|
|
|
|
|
|
get: (id: number): Promise<Child> =>
|
|
|
|
|
publicApi.get(`/public/mine/children/${id}`),
|
|
|
|
|
|
|
|
|
|
update: (id: number, data: Partial<CreateChildParams>): Promise<Child> =>
|
|
|
|
|
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<any> =>
|
|
|
|
|
publicApi.post("/public/children/create-account", data),
|
|
|
|
|
|
|
|
|
|
// 获取子女账号列表
|
|
|
|
|
list: (): Promise<ChildAccount[]> =>
|
|
|
|
|
publicApi.get("/public/children/accounts"),
|
|
|
|
|
|
|
|
|
|
// 家长切换到子女身份
|
|
|
|
|
switchToChild: (childUserId: number): Promise<LoginResponse> =>
|
|
|
|
|
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<any> =>
|
|
|
|
|
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
|
|
|
|
|
organizers: any
|
|
|
|
|
visibility: 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) => 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(`/public/activities/${id}/my-registration`),
|
|
|
|
|
|
|
|
|
|
submitWork: (
|
|
|
|
|
id: number,
|
|
|
|
|
data: {
|
|
|
|
|
registrationId: 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),
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-31 13:56:20 +08:00
|
|
|
// ==================== 我的报名 ====================
|
2026-03-27 22:20:25 +08:00
|
|
|
|
|
|
|
|
export const publicMineApi = {
|
|
|
|
|
registrations: (params?: { page?: number; pageSize?: number }) =>
|
|
|
|
|
publicApi.get("/public/mine/registrations", { params }),
|
2026-03-31 13:56:20 +08:00
|
|
|
}
|
2026-03-27 22:20:25 +08:00
|
|
|
|
2026-03-31 13:56:20 +08:00
|
|
|
// ==================== 点赞 & 收藏 ====================
|
|
|
|
|
|
|
|
|
|
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 }),
|
2026-03-27 22:20:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ==================== 用户作品库 ====================
|
|
|
|
|
|
|
|
|
|
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<UserWork> => 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<UserWork> =>
|
|
|
|
|
publicApi.get(`/public/works/${id}`),
|
|
|
|
|
|
|
|
|
|
// 更新作品
|
|
|
|
|
update: (id: number, data: {
|
|
|
|
|
title?: string
|
|
|
|
|
description?: string
|
|
|
|
|
coverUrl?: string
|
|
|
|
|
visibility?: string
|
|
|
|
|
tagIds?: number[]
|
|
|
|
|
}): Promise<UserWork> => 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<UserWorkPage[]> =>
|
|
|
|
|
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),
|
|
|
|
|
|
|
|
|
|
// 查询生成进度
|
|
|
|
|
getStatus: (id: number): Promise<{ id: number; status: string; title: string; createdAt: string }> =>
|
|
|
|
|
publicApi.get(`/public/creation/${id}/status`),
|
|
|
|
|
|
|
|
|
|
// 获取生成结果
|
|
|
|
|
getResult: (id: number): Promise<UserWork> =>
|
|
|
|
|
publicApi.get(`/public/creation/${id}/result`),
|
|
|
|
|
|
|
|
|
|
// 创作历史
|
|
|
|
|
history: (params?: { page?: number; pageSize?: number }): Promise<{ list: any[]; total: number }> =>
|
|
|
|
|
publicApi.get("/public/creation/history", { params }),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ==================== 标签 ====================
|
|
|
|
|
|
|
|
|
|
export interface WorkTag {
|
|
|
|
|
id: number
|
|
|
|
|
name: string
|
|
|
|
|
category: string | null
|
|
|
|
|
usageCount: number
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export const publicTagsApi = {
|
|
|
|
|
list: (): Promise<WorkTag[]> => publicApi.get("/public/tags"),
|
|
|
|
|
hot: (): Promise<WorkTag[]> => publicApi.get("/public/tags/hot"),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ==================== 作品广场 ====================
|
|
|
|
|
|
|
|
|
|
export const publicGalleryApi = {
|
2026-03-31 15:21:21 +08:00
|
|
|
recommended: (): Promise<UserWork[]> =>
|
|
|
|
|
publicApi.get("/public/gallery/recommended"),
|
|
|
|
|
|
2026-03-27 22:20:25 +08:00
|
|
|
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<UserWork> =>
|
|
|
|
|
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
|