|
@@ -0,0 +1,474 @@
|
|
|
|
|
+/**
|
|
|
|
|
+ * 后台管理系统API请求工具类
|
|
|
|
|
+ * 最后更新: 2025-01-11
|
|
|
|
|
+ */
|
|
|
|
|
+
|
|
|
|
|
+// API基础URL - 后端服务运行在8001端口
|
|
|
|
|
+const BASE_URL = 'http://localhost:8001'
|
|
|
|
|
+
|
|
|
|
|
+// 调试:输出BASE_URL(生产环境可删除)
|
|
|
|
|
+console.log('API Base URL:', BASE_URL)
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 统一请求方法
|
|
|
|
|
+ */
|
|
|
|
|
+function request(url, method = 'GET', data = {}, token = '') {
|
|
|
|
|
+ return new Promise((resolve, reject) => {
|
|
|
|
|
+ const headers = {
|
|
|
|
|
+ 'Content-Type': 'application/json'
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 如果有token,添加到请求头
|
|
|
|
|
+ if (token) {
|
|
|
|
|
+ headers['Authorization'] = token
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 构建请求URL
|
|
|
|
|
+ let requestUrl = BASE_URL + url
|
|
|
|
|
+ console.log('请求URL:', requestUrl, '方法:', method) // 调试输出
|
|
|
|
|
+ if (method === 'GET' && data && Object.keys(data).length > 0) {
|
|
|
|
|
+ const queryParams = new URLSearchParams()
|
|
|
|
|
+ for (const key in data) {
|
|
|
|
|
+ if (data[key] !== undefined && data[key] !== null && data[key] !== '') {
|
|
|
|
|
+ queryParams.append(key, data[key])
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ const queryString = queryParams.toString()
|
|
|
|
|
+ if (queryString) {
|
|
|
|
|
+ requestUrl += (url.includes('?') ? '&' : '?') + queryString
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ fetch(requestUrl, {
|
|
|
|
|
+ method: method,
|
|
|
|
|
+ headers: headers,
|
|
|
|
|
+ body: method !== 'GET' && data ? JSON.stringify(data) : undefined
|
|
|
|
|
+ })
|
|
|
|
|
+ .then(response => {
|
|
|
|
|
+ if (!response.ok) {
|
|
|
|
|
+ throw new Error(`HTTP error! status: ${response.status}`)
|
|
|
|
|
+ }
|
|
|
|
|
+ return response.json()
|
|
|
|
|
+ })
|
|
|
|
|
+ .then(res => {
|
|
|
|
|
+ console.log('API响应:', url, res)
|
|
|
|
|
+ if (res && res.code === 200) {
|
|
|
|
|
+ resolve(res)
|
|
|
|
|
+ } else {
|
|
|
|
|
+ reject(new Error(res.message || res.msg || '请求失败'))
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ .catch(err => {
|
|
|
|
|
+ console.error('API请求失败:', err)
|
|
|
|
|
+ // 更详细的错误信息
|
|
|
|
|
+ if (err.name === 'TypeError' && err.message.includes('Failed to fetch')) {
|
|
|
|
|
+ reject(new Error('无法连接到后端服务,请检查:\n1. 后端服务是否启动(端口8001)\n2. 后端服务地址是否正确\n3. 是否存在CORS问题'))
|
|
|
|
|
+ } else if (err.message.includes('HTTP error')) {
|
|
|
|
|
+ reject(new Error(`服务器错误: ${err.message}`))
|
|
|
|
|
+ } else {
|
|
|
|
|
+ reject(new Error(err.message || '网络请求失败,请检查后端服务'))
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ })
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// ============================================
|
|
|
|
|
+// 管理员相关API
|
|
|
|
|
+// ============================================
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 管理员登录
|
|
|
|
|
+ */
|
|
|
|
|
+export function adminLogin(username, password) {
|
|
|
|
|
+ return request('/api/admin/login', 'POST', {
|
|
|
|
|
+ username: username,
|
|
|
|
|
+ password: password
|
|
|
|
|
+ })
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// ============================================
|
|
|
|
|
+// 书籍管理API
|
|
|
|
|
+// ============================================
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 分页查询书籍
|
|
|
|
|
+ */
|
|
|
|
|
+export function getAdminBooks(params, token) {
|
|
|
|
|
+ return request('/api/admin/book/list', 'GET', params || {}, token)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 根据ID查询书籍
|
|
|
|
|
+ */
|
|
|
|
|
+export function getAdminBookById(id, token) {
|
|
|
|
|
+ return request(`/api/admin/book/${id}`, 'GET', {}, token)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 创建书籍
|
|
|
|
|
+ */
|
|
|
|
|
+export function createAdminBook(bookData, token) {
|
|
|
|
|
+ return request('/api/admin/book', 'POST', bookData, token)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 更新书籍
|
|
|
|
|
+ */
|
|
|
|
|
+export function updateAdminBook(id, bookData, token) {
|
|
|
|
|
+ return request(`/api/admin/book/${id}`, 'PUT', bookData, token)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 删除书籍
|
|
|
|
|
+ */
|
|
|
|
|
+export function deleteAdminBook(id, token) {
|
|
|
|
|
+ return request(`/api/admin/book/${id}`, 'DELETE', {}, token)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 批量删除书籍
|
|
|
|
|
+ */
|
|
|
|
|
+export function deleteAdminBooks(ids, token) {
|
|
|
|
|
+ return request('/api/admin/book/batch', 'DELETE', ids, token)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 上架书籍
|
|
|
|
|
+ */
|
|
|
|
|
+export function publishAdminBook(id, token) {
|
|
|
|
|
+ return request(`/api/admin/book/${id}/publish`, 'PUT', {}, token)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 下架书籍
|
|
|
|
|
+ */
|
|
|
|
|
+export function unpublishAdminBook(id, token) {
|
|
|
|
|
+ return request(`/api/admin/book/${id}/unpublish`, 'PUT', {}, token)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 批量上架书籍
|
|
|
|
|
+ */
|
|
|
|
|
+export function publishAdminBooks(ids, token) {
|
|
|
|
|
+ return request('/api/admin/book/batch/publish', 'PUT', { ids: ids }, token)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 批量下架书籍
|
|
|
|
|
+ */
|
|
|
|
|
+export function unpublishAdminBooks(ids, token) {
|
|
|
|
|
+ return request('/api/admin/book/batch/unpublish', 'PUT', { ids: ids }, token)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// ============================================
|
|
|
|
|
+// 听书管理API
|
|
|
|
|
+// ============================================
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 分页查询听书
|
|
|
|
|
+ */
|
|
|
|
|
+export function getAdminAudiobooks(params, token) {
|
|
|
|
|
+ return request('/api/admin/audiobook/list', 'GET', params || {}, token)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 根据ID查询听书
|
|
|
|
|
+ */
|
|
|
|
|
+export function getAdminAudiobookById(id, token) {
|
|
|
|
|
+ return request(`/api/admin/audiobook/${id}`, 'GET', {}, token)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 创建听书
|
|
|
|
|
+ */
|
|
|
|
|
+export function createAdminAudiobook(data, token) {
|
|
|
|
|
+ return request('/api/admin/audiobook', 'POST', data, token)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 更新听书
|
|
|
|
|
+ */
|
|
|
|
|
+export function updateAdminAudiobook(id, data, token) {
|
|
|
|
|
+ return request(`/api/admin/audiobook/${id}`, 'PUT', data, token)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 删除听书
|
|
|
|
|
+ */
|
|
|
|
|
+export function deleteAdminAudiobook(id, token) {
|
|
|
|
|
+ return request(`/api/admin/audiobook/${id}`, 'DELETE', {}, token)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 批量删除听书
|
|
|
|
|
+ */
|
|
|
|
|
+export function deleteAdminAudiobooks(ids, token) {
|
|
|
|
|
+ return request('/api/admin/audiobook/batch', 'DELETE', ids, token)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 上架听书
|
|
|
|
|
+ */
|
|
|
|
|
+export function publishAdminAudiobook(id, token) {
|
|
|
|
|
+ return request(`/api/admin/audiobook/${id}/publish`, 'PUT', {}, token)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 下架听书
|
|
|
|
|
+ */
|
|
|
|
|
+export function unpublishAdminAudiobook(id, token) {
|
|
|
|
|
+ return request(`/api/admin/audiobook/${id}/unpublish`, 'PUT', {}, token)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 批量上架听书
|
|
|
|
|
+ */
|
|
|
|
|
+export function publishAdminAudiobooks(ids, token) {
|
|
|
|
|
+ return request('/api/admin/audiobook/batch/publish', 'PUT', { ids: ids }, token)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 批量下架听书
|
|
|
|
|
+ */
|
|
|
|
|
+export function unpublishAdminAudiobooks(ids, token) {
|
|
|
|
|
+ return request('/api/admin/audiobook/batch/unpublish', 'PUT', { ids: ids }, token)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// ============================================
|
|
|
|
|
+// 分类相关API(用于下拉选择)
|
|
|
|
|
+// ============================================
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 获取所有分类(用于后台管理)
|
|
|
|
|
+ */
|
|
|
|
|
+export function getAllCategories(token) {
|
|
|
|
|
+ return request('/api/category/list', 'GET', {}, token || '')
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// ============================================
|
|
|
|
|
+// 章节管理API
|
|
|
|
|
+// ============================================
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 根据书籍ID获取章节列表
|
|
|
|
|
+ */
|
|
|
|
|
+export function getAdminChapters(bookId, token) {
|
|
|
|
|
+ return request('/api/admin/chapter/list', 'GET', { bookId: bookId }, token)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 根据章节ID获取章节详情(包含内容)
|
|
|
|
|
+ */
|
|
|
|
|
+export function getAdminChapterById(id, token) {
|
|
|
|
|
+ return request(`/api/admin/chapter/${id}`, 'GET', {}, token)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 创建章节
|
|
|
|
|
+ */
|
|
|
|
|
+export function createAdminChapter(chapterData, token) {
|
|
|
|
|
+ return request('/api/admin/chapter/create', 'POST', chapterData, token)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 更新章节
|
|
|
|
|
+ */
|
|
|
|
|
+export function updateAdminChapter(chapterData, token) {
|
|
|
|
|
+ return request('/api/admin/chapter/update', 'PUT', chapterData, token)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 删除章节
|
|
|
|
|
+ */
|
|
|
|
|
+export function deleteAdminChapter(id, token) {
|
|
|
|
|
+ return request(`/api/admin/chapter/${id}`, 'DELETE', {}, token)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 批量删除章节
|
|
|
|
|
+ */
|
|
|
|
|
+export function deleteAdminChapters(chapterIds, token) {
|
|
|
|
|
+ return request('/api/admin/chapter/batch-delete', 'POST', { chapterIds: chapterIds }, token)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// ============================================
|
|
|
|
|
+// 轮播图管理API
|
|
|
|
|
+// ============================================
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 获取所有轮播图分组
|
|
|
|
|
+ */
|
|
|
|
|
+export function getBannerGroups(token) {
|
|
|
|
|
+ return request('/api/admin/banner/groups', 'GET', {}, token)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 创建轮播图分组
|
|
|
|
|
+ */
|
|
|
|
|
+export function createBannerGroup(groupData, token) {
|
|
|
|
|
+ return request('/api/admin/banner/groups', 'POST', groupData, token)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 更新轮播图分组
|
|
|
|
|
+ */
|
|
|
|
|
+export function updateBannerGroup(id, groupData, token) {
|
|
|
|
|
+ return request(`/api/admin/banner/groups/${id}`, 'PUT', groupData, token)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 删除轮播图分组
|
|
|
|
|
+ */
|
|
|
|
|
+export function deleteBannerGroup(id, token) {
|
|
|
|
|
+ return request(`/api/admin/banner/groups/${id}`, 'DELETE', {}, token)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 获取轮播图列表
|
|
|
|
|
+ */
|
|
|
|
|
+export function getBanners(groupId, status, token) {
|
|
|
|
|
+ const params = { groupId: groupId }
|
|
|
|
|
+ if (status !== undefined && status !== null) {
|
|
|
|
|
+ params.status = status
|
|
|
|
|
+ }
|
|
|
|
|
+ return request('/api/admin/banner/list', 'GET', params, token)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 创建轮播图
|
|
|
|
|
+ */
|
|
|
|
|
+export function createBanner(bannerData, token) {
|
|
|
|
|
+ return request('/api/admin/banner', 'POST', bannerData, token)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 更新轮播图
|
|
|
|
|
+ */
|
|
|
|
|
+export function updateBanner(id, bannerData, token) {
|
|
|
|
|
+ return request(`/api/admin/banner/${id}`, 'PUT', bannerData, token)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 删除轮播图
|
|
|
|
|
+ */
|
|
|
|
|
+export function deleteBanner(id, token) {
|
|
|
|
|
+ return request(`/api/admin/banner/${id}`, 'DELETE', {}, token)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// ============================================
|
|
|
|
|
+// 排行榜管理API
|
|
|
|
|
+// ============================================
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 获取所有排行榜组
|
|
|
|
|
+ */
|
|
|
|
|
+export function getRankingGroups(token) {
|
|
|
|
|
+ return request('/api/admin/ranking/groups', 'GET', {}, token)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 创建排行榜组
|
|
|
|
|
+ */
|
|
|
|
|
+export function createRankingGroup(groupData, token) {
|
|
|
|
|
+ return request('/api/admin/ranking/groups', 'POST', groupData, token)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 更新排行榜组
|
|
|
|
|
+ */
|
|
|
|
|
+export function updateRankingGroup(id, groupData, token) {
|
|
|
|
|
+ return request(`/api/admin/ranking/groups/${id}`, 'PUT', groupData, token)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 删除排行榜组
|
|
|
|
|
+ */
|
|
|
|
|
+export function deleteRankingGroup(id, token) {
|
|
|
|
|
+ return request(`/api/admin/ranking/groups/${id}`, 'DELETE', {}, token)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 获取排行榜项(包含书籍信息,支持按分类筛选)
|
|
|
|
|
+ */
|
|
|
|
|
+export function getRankingItemsWithBooks(groupId, categoryId, status, token) {
|
|
|
|
|
+ const params = { groupId: groupId }
|
|
|
|
|
+ if (categoryId !== undefined && categoryId !== null) {
|
|
|
|
|
+ params.categoryId = categoryId
|
|
|
|
|
+ }
|
|
|
|
|
+ if (status !== undefined && status !== null) {
|
|
|
|
|
+ params.status = status
|
|
|
|
|
+ }
|
|
|
|
|
+ return request('/api/admin/ranking/items/with-books', 'GET', params, token)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 批量更新排序
|
|
|
|
|
+ */
|
|
|
|
|
+export function batchUpdateRankingSort(sortData, token) {
|
|
|
|
|
+ return request('/api/admin/ranking/sort', 'POST', sortData, token)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 添加书籍到排行榜
|
|
|
|
|
+ */
|
|
|
|
|
+export function addBookToRanking(groupId, bookId, categoryId, token) {
|
|
|
|
|
+ const params = { groupId: groupId, bookId: bookId }
|
|
|
|
|
+ if (categoryId !== undefined && categoryId !== null) {
|
|
|
|
|
+ params.categoryId = categoryId
|
|
|
|
|
+ }
|
|
|
|
|
+ return request('/api/admin/ranking/items/add', 'POST', params, token)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 从排行榜移除书籍
|
|
|
|
|
+ */
|
|
|
|
|
+export function removeBookFromRanking(itemId, token) {
|
|
|
|
|
+ return request(`/api/admin/ranking/items/${itemId}/remove`, 'DELETE', {}, token)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// ============================================
|
|
|
|
|
+// 用户管理API
|
|
|
|
|
+// ============================================
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 分页查询用户
|
|
|
|
|
+ */
|
|
|
|
|
+export function getAdminUsers(params, token) {
|
|
|
|
|
+ return request('/api/admin/user/list', 'GET', params || {}, token)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 根据ID查询用户
|
|
|
|
|
+ */
|
|
|
|
|
+export function getAdminUserById(id, token) {
|
|
|
|
|
+ return request(`/api/admin/user/${id}`, 'GET', {}, token)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 更新用户信息
|
|
|
|
|
+ */
|
|
|
|
|
+export function updateAdminUser(id, userData, token) {
|
|
|
|
|
+ return request(`/api/admin/user/${id}`, 'PUT', userData, token)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 禁用用户
|
|
|
|
|
+ */
|
|
|
|
|
+export function disableAdminUser(id, token) {
|
|
|
|
|
+ return request(`/api/admin/user/${id}/disable`, 'PUT', {}, token)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 启用用户
|
|
|
|
|
+ */
|
|
|
|
|
+export function enableAdminUser(id, token) {
|
|
|
|
|
+ return request(`/api/admin/user/${id}/enable`, 'PUT', {}, token)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 重置用户密码
|
|
|
|
|
+ */
|
|
|
|
|
+export function resetAdminUserPassword(id, password, token) {
|
|
|
|
|
+ return request(`/api/admin/user/${id}/reset-password`, 'PUT', { password: password }, token)
|
|
|
|
|
+}
|
|
|
|
|
+
|