Files
nl-blogs/client/src/services/api.ts

1868 lines
51 KiB
TypeScript
Raw Normal View History

2026-01-20 10:36:27 +08:00
export const API_BASE = '/api'
2026-01-15 13:51:44 +08:00
// 通用请求头配置
export const getAuthHeaders = () => {
const token = localStorage.getItem('token')
return {
'Content-Type': 'application/json',
...(token ? { Authorization: `Bearer ${token}` } : {})
}
}
// 认证相关类型
export interface User {
id: number
username: string
email: string
role: string
isActive: number
createdAt: string
updatedAt: string
}
export interface LoginRequest {
username: string
password: string
}
export interface LoginResponse {
token: string
user: User
expire: number
}
// 角色相关类型
export interface Role {
id: number
name: string
description: string
createdAt: string
updatedAt: string
}
// 作品相关类型
export interface Work {
id: string
title: string
category: string
year: string
heroImg: string
desc: string
techStack: { category: string; items: string[] }[]
gallery: string[]
2026-01-19 21:19:35 +08:00
links: { live?: string; github?: string; demo?: string }
2026-01-15 13:51:44 +08:00
next: string
}
2026-01-16 17:03:34 +08:00
// 分类相关类型
export interface Category {
id: number
name: string
slug: string
description: string
sortOrder: number
createdAt: string
updatedAt: string
}
// 专栏相关类型
export interface Column {
id: number
name: string
description: string
cover: string
isActive: number
sortOrder: number
createdAt: string
updatedAt: string
}
// 标签相关类型
export interface Tag {
id: number
name: string
slug: string
createdAt: string
updatedAt: string
}
2026-01-15 13:51:44 +08:00
// 文章相关类型
export interface Post {
2026-01-15 17:03:59 +08:00
id: number
2026-01-15 13:51:44 +08:00
title: string
2026-01-16 17:03:34 +08:00
categoryId: number
categoryName?: string // Display name
categorySlug?: string
category?: Category // Optional full object
2026-01-19 16:14:08 +08:00
columnId?: number | null
columnName?: string
2026-01-16 17:03:34 +08:00
tags?: Tag[]
2026-01-15 13:51:44 +08:00
date: string
excerpt?: string
content?: string
isPublished?: number
2026-01-16 17:03:34 +08:00
readCount?: number
2026-01-15 13:51:44 +08:00
}
export interface PostHistory {
id: number
2026-01-15 17:03:59 +08:00
postId: number
2026-01-15 13:51:44 +08:00
version: number
title: string
2026-01-16 17:03:34 +08:00
categoryId: number
2026-01-15 13:51:44 +08:00
excerpt?: string
content: string
isPublished: number
modifiedBy: number
modifiedAt: string
createdAt: string
}
// 代码片段相关类型
export interface Snippet {
id: string
title: string
code: string
type: string
description?: string
viewCount?: number
}
// 系统配置相关类型
export interface Setting {
id: number
keyName: string
value: string
description: string
createdAt: string
updatedAt: string
}
// 操作日志相关类型
export interface OperationLog {
id: number
userId: number
username: string
ip: string
2026-01-20 14:31:39 +08:00
region?: string
2026-01-15 13:51:44 +08:00
path: string
method: string
2026-01-20 15:23:37 +08:00
action?: string
2026-01-15 13:51:44 +08:00
params: string
status: number
duration: number
createdAt: string
}
// 分页响应类型
export interface PaginationResponse<T> {
list: T[]
total: number
page: number
size: number
}
// 登录API
export const login = async (credentials: LoginRequest): Promise<LoginResponse> => {
try {
const response = await fetch(`${API_BASE}/admin/login`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(credentials),
})
if (!response.ok) {
const errorData = await response.json()
2026-01-16 17:03:34 +08:00
throw new Error(errorData.message || '登录失败')
}
const data = await response.json()
const result = data.result as { token: string; user: User }
return {
token: result.token,
user: result.user,
expire: 24 * 60 * 60 * 1000 // 24小时
2026-01-15 13:51:44 +08:00
}
} catch (error) {
console.error('Login error:', error)
throw error
}
}
// 用户管理API
export const getUsers = async (): Promise<User[]> => {
try {
const response = await fetch(`${API_BASE}/admin/users`, {
headers: getAuthHeaders()
})
if (!response.ok) {
const errorData = await response.json()
2026-01-16 17:03:34 +08:00
throw new Error(errorData.message || '获取用户列表失败')
2026-01-15 13:51:44 +08:00
}
2026-01-16 17:03:34 +08:00
const data = await response.json()
// 后端返回的是分页格式 {list, total, page, size},需要从 result.list 中取值
return (data.result?.list || []) as User[]
2026-01-15 13:51:44 +08:00
} catch (error) {
console.error('Get users error:', error)
throw error
}
}
export const fetchUser = async (id: number): Promise<User> => {
try {
const response = await fetch(`${API_BASE}/admin/users/${id}`, {
headers: getAuthHeaders()
})
if (!response.ok) {
const errorData = await response.json()
2026-01-16 17:03:34 +08:00
throw new Error(errorData.message || '获取用户详情失败')
2026-01-15 13:51:44 +08:00
}
2026-01-16 17:03:34 +08:00
const data = await response.json()
return data.result
2026-01-15 13:51:44 +08:00
} catch (error) {
console.error(`Error fetching user ${id}:`, error)
throw error
}
}
export const createUser = async (userData: Omit<User, 'id' | 'createdAt' | 'updatedAt'>): Promise<void> => {
try {
const response = await fetch(`${API_BASE}/admin/users`, {
method: 'POST',
headers: getAuthHeaders(),
body: JSON.stringify(userData)
})
if (!response.ok) {
const errorData = await response.json()
2026-01-16 17:03:34 +08:00
throw new Error(errorData.message || '创建用户失败')
2026-01-15 13:51:44 +08:00
}
} catch (error) {
console.error('Create user error:', error)
throw error
}
}
export const updateUser = async (id: number, userData: Omit<User, 'id' | 'createdAt' | 'updatedAt'>): Promise<void> => {
try {
const response = await fetch(`${API_BASE}/admin/users/${id}`, {
method: 'PUT',
headers: getAuthHeaders(),
body: JSON.stringify(userData)
})
if (!response.ok) {
const errorData = await response.json()
2026-01-16 17:03:34 +08:00
throw new Error(errorData.message || '更新用户失败')
2026-01-15 13:51:44 +08:00
}
} catch (error) {
console.error('Update user error:', error)
throw error
}
}
export const deleteUser = async (id: number): Promise<void> => {
try {
const response = await fetch(`${API_BASE}/admin/users/${id}`, {
method: 'DELETE',
headers: getAuthHeaders()
})
if (!response.ok) {
const errorData = await response.json()
2026-01-16 17:03:34 +08:00
throw new Error(errorData.message || '删除用户失败')
2026-01-15 13:51:44 +08:00
}
} catch (error) {
console.error('Delete user error:', error)
throw error
}
}
// 角色管理API
export const getRoles = async (): Promise<Role[]> => {
try {
const response = await fetch(`${API_BASE}/admin/roles`, {
headers: getAuthHeaders()
})
if (!response.ok) {
const errorData = await response.json()
2026-01-16 17:03:34 +08:00
throw new Error(errorData.message || '获取角色列表失败')
2026-01-15 13:51:44 +08:00
}
2026-01-16 17:03:34 +08:00
const data = await response.json()
return data.result || []
2026-01-15 13:51:44 +08:00
} catch (error) {
console.error('Get roles error:', error)
throw error
}
}
export const createRole = async (roleData: Omit<Role, 'id' | 'createdAt' | 'updatedAt'>): Promise<void> => {
try {
const response = await fetch(`${API_BASE}/admin/roles`, {
method: 'POST',
headers: getAuthHeaders(),
body: JSON.stringify(roleData)
})
if (!response.ok) {
const errorData = await response.json()
2026-01-16 17:03:34 +08:00
throw new Error(errorData.message || '创建角色失败')
2026-01-15 13:51:44 +08:00
}
} catch (error) {
console.error('Create role error:', error)
throw error
}
}
export const updateRole = async (id: number, roleData: Omit<Role, 'id' | 'createdAt' | 'updatedAt'>): Promise<void> => {
try {
const response = await fetch(`${API_BASE}/admin/roles/${id}`, {
method: 'PUT',
headers: getAuthHeaders(),
body: JSON.stringify(roleData)
})
if (!response.ok) {
const errorData = await response.json()
2026-01-16 17:03:34 +08:00
throw new Error(errorData.message || '更新角色失败')
2026-01-15 13:51:44 +08:00
}
} catch (error) {
console.error('Update role error:', error)
throw error
}
}
export const deleteRole = async (id: number): Promise<void> => {
try {
const response = await fetch(`${API_BASE}/admin/roles/${id}`, {
method: 'DELETE',
headers: getAuthHeaders()
})
if (!response.ok) {
const errorData = await response.json()
2026-01-16 17:03:34 +08:00
throw new Error(errorData.message || '删除角色失败')
2026-01-15 13:51:44 +08:00
}
} catch (error) {
console.error('Delete role error:', error)
throw error
}
}
export const fetchRole = async (id: number): Promise<Role> => {
try {
const response = await fetch(`${API_BASE}/admin/roles/${id}`, {
headers: getAuthHeaders()
})
if (!response.ok) {
const errorData = await response.json()
2026-01-16 17:03:34 +08:00
throw new Error(errorData.message || '获取角色详情失败')
2026-01-15 13:51:44 +08:00
}
2026-01-16 17:03:34 +08:00
const data = await response.json()
return data.result
2026-01-15 13:51:44 +08:00
} catch (error) {
console.error(`Error fetching role ${id}:`, error)
throw error
}
}
// 作品管理API
export const getAdminWorks = async (): Promise<Work[]> => {
try {
const response = await fetch(`${API_BASE}/admin/works`, {
headers: getAuthHeaders()
})
if (!response.ok) {
const errorData = await response.json()
2026-01-16 17:03:34 +08:00
throw new Error(errorData.message || '获取作品列表失败')
2026-01-15 13:51:44 +08:00
}
2026-01-16 17:03:34 +08:00
const data = await response.json()
// 后端返回的是分页格式 {list, total, page, size},需要从 result.list 中取值
// 确保始终返回数组,即使 result 或 result.list 为 null/undefined
const list = data.result?.list
return (list && Array.isArray(list)) ? list : []
2026-01-15 13:51:44 +08:00
} catch (error) {
console.error('Get admin works error:', error)
throw error
}
}
export const fetchWorks = async (): Promise<Work[]> => {
try {
const response = await fetch(`${API_BASE}/works`)
2026-01-16 17:03:34 +08:00
if (!response.ok) {
const errorData = await response.json()
throw new Error(errorData.message || 'Failed to fetch works')
}
const data = await response.json()
// 确保从 result 字段取值,并确保始终返回数组
const result = data.result
if (!result) {
return []
}
if (!Array.isArray(result)) {
return []
}
// 确保每个 work 对象的字段格式正确
return result.map((work: any) => ({
id: work.id || '',
title: work.title || '',
category: work.category || '',
year: work.year || '',
heroImg: work.heroImg || '',
desc: work.desc || '',
techStack: Array.isArray(work.techStack) ? work.techStack : [],
gallery: Array.isArray(work.gallery) ? work.gallery : [],
2026-01-19 21:19:35 +08:00
links: work.links || {},
2026-01-16 17:03:34 +08:00
next: work.next || ''
})) as Work[]
2026-01-15 13:51:44 +08:00
} catch (error) {
console.error('Error fetching works:', error)
return []
}
}
export const fetchWork = async (id: string): Promise<Work> => {
try {
const response = await fetch(`${API_BASE}/works/${id}`)
if (!response.ok) throw new Error('Failed to fetch work')
2026-01-16 17:03:34 +08:00
const data = await response.json()
// 确保从 result 字段取值
const result = data.result as Work
if (!result) {
throw new Error('Work not found')
}
// 确保 techStack 和 gallery 始终是数组
if (!Array.isArray(result.techStack)) {
result.techStack = []
}
if (!Array.isArray(result.gallery)) {
result.gallery = []
}
return result
2026-01-15 13:51:44 +08:00
} catch (error) {
console.error(`Error fetching work ${id}:`, error)
return {
id: 'default',
title: '默认作品',
category: '默认分类',
year: '2024',
heroImg: '',
desc: '',
techStack: [],
gallery: [],
2026-01-19 21:19:35 +08:00
links: {},
2026-01-15 13:51:44 +08:00
next: ''
}
}
}
export const createWork = async (workData: Omit<Work, 'id' | 'next'>): Promise<void> => {
try {
const response = await fetch(`${API_BASE}/admin/works`, {
method: 'POST',
headers: getAuthHeaders(),
body: JSON.stringify(workData)
})
if (!response.ok) {
const errorData = await response.json()
2026-01-16 17:03:34 +08:00
throw new Error(errorData.message || '创建作品失败')
2026-01-15 13:51:44 +08:00
}
} catch (error) {
console.error('Create work error:', error)
throw error
}
}
export const updateWork = async (id: string, workData: Omit<Work, 'id' | 'next'>): Promise<void> => {
try {
const response = await fetch(`${API_BASE}/admin/works/${id}`, {
method: 'PUT',
headers: getAuthHeaders(),
body: JSON.stringify(workData)
})
if (!response.ok) {
const errorData = await response.json()
2026-01-16 17:03:34 +08:00
throw new Error(errorData.message || '更新作品失败')
2026-01-15 13:51:44 +08:00
}
} catch (error) {
console.error('Update work error:', error)
throw error
}
}
export const deleteWork = async (id: string): Promise<void> => {
try {
const response = await fetch(`${API_BASE}/admin/works/${id}`, {
method: 'DELETE',
headers: getAuthHeaders()
})
if (!response.ok) {
const errorData = await response.json()
2026-01-16 17:03:34 +08:00
throw new Error(errorData.message || '删除作品失败')
2026-01-15 13:51:44 +08:00
}
} catch (error) {
console.error('Delete work error:', error)
throw error
}
}
// 文章管理API
2026-01-16 17:03:34 +08:00
export const getAdminPosts = async (): Promise<PaginationResponse<Post>> => {
2026-01-15 13:51:44 +08:00
try {
2026-01-16 17:03:34 +08:00
const response = await fetch(`${API_BASE}/admin/posts?pageSize=1000`, {
2026-01-15 13:51:44 +08:00
headers: getAuthHeaders()
})
if (!response.ok) {
const errorData = await response.json()
2026-01-16 17:03:34 +08:00
throw new Error(errorData.message || '获取文章列表失败')
2026-01-15 13:51:44 +08:00
}
2026-01-16 17:03:34 +08:00
const data = await response.json()
return data.result
2026-01-15 13:51:44 +08:00
} catch (error) {
console.error('Get admin posts error:', error)
throw error
}
}
2026-01-19 16:14:08 +08:00
export const fetchPosts = async (query?: string, categoryId?: number, tagId?: number, columnId?: number): Promise<Post[]> => {
2026-01-15 13:51:44 +08:00
try {
2026-01-15 17:03:59 +08:00
let url = `${API_BASE}/posts`
2026-01-16 17:03:34 +08:00
const params = new URLSearchParams()
if (query) params.append('q', query)
if (categoryId) params.append('category', categoryId.toString())
if (tagId) params.append('tag', tagId.toString())
2026-01-19 16:14:08 +08:00
if (columnId) params.append('column', columnId.toString())
2026-01-16 17:03:34 +08:00
if (params.toString()) {
url += `?${params.toString()}`
2026-01-15 17:03:59 +08:00
}
2026-01-16 17:03:34 +08:00
2026-01-15 17:03:59 +08:00
const response = await fetch(url)
2026-01-15 13:51:44 +08:00
if (!response.ok) throw new Error('Failed to fetch posts')
2026-01-16 17:03:34 +08:00
const data = await response.json()
return data.result || []
2026-01-15 13:51:44 +08:00
} catch (error) {
console.error('Error fetching posts:', error)
return []
}
}
2026-01-15 17:03:59 +08:00
export const fetchPost = async (id: number | string): Promise<Post> => {
2026-01-15 13:51:44 +08:00
try {
const response = await fetch(`${API_BASE}/posts/${id}`)
if (!response.ok) throw new Error('Failed to fetch post')
2026-01-16 17:03:34 +08:00
const data = await response.json()
return data.result
2026-01-15 13:51:44 +08:00
} catch (error) {
console.error(`Error fetching post ${id}:`, error)
2026-01-16 17:03:34 +08:00
// Return empty fallback
2026-01-15 13:51:44 +08:00
return {
2026-01-15 17:03:59 +08:00
id: Number(id),
2026-01-16 17:03:34 +08:00
title: '未知文章',
categoryId: 0,
2026-01-15 13:51:44 +08:00
date: '2024-01-01'
}
}
}
export const createPost = async (postData: Omit<Post, 'id'>): Promise<void> => {
try {
const response = await fetch(`${API_BASE}/admin/posts`, {
method: 'POST',
headers: getAuthHeaders(),
body: JSON.stringify(postData)
})
if (!response.ok) {
const errorData = await response.json()
2026-01-16 17:03:34 +08:00
throw new Error(errorData.message || '创建文章失败')
2026-01-15 13:51:44 +08:00
}
} catch (error) {
console.error('Create post error:', error)
throw error
}
}
2026-01-15 17:03:59 +08:00
export const updatePost = async (id: number | string, postData: Omit<Post, 'id'>): Promise<void> => {
2026-01-15 13:51:44 +08:00
try {
const response = await fetch(`${API_BASE}/admin/posts/${id}`, {
method: 'PUT',
headers: getAuthHeaders(),
body: JSON.stringify(postData)
})
if (!response.ok) {
const errorData = await response.json()
2026-01-16 17:03:34 +08:00
throw new Error(errorData.message || '更新文章失败')
2026-01-15 13:51:44 +08:00
}
} catch (error) {
console.error('Update post error:', error)
throw error
}
}
2026-01-16 17:03:34 +08:00
export const togglePostStatus = async (id: number, isPublished: number): Promise<void> => {
try {
const response = await fetch(`${API_BASE}/admin/posts/${id}/status`, {
method: 'PATCH',
headers: getAuthHeaders(),
body: JSON.stringify({ isPublished })
})
if (!response.ok) {
const errorData = await response.json()
throw new Error(errorData.message || '更新状态失败')
}
} catch (error) {
console.error('Toggle post status error:', error)
throw error
}
}
2026-01-15 17:03:59 +08:00
export const deletePost = async (id: number | string): Promise<void> => {
2026-01-15 13:51:44 +08:00
try {
const response = await fetch(`${API_BASE}/admin/posts/${id}`, {
method: 'DELETE',
headers: getAuthHeaders()
})
if (!response.ok) {
const errorData = await response.json()
2026-01-16 17:03:34 +08:00
throw new Error(errorData.message || '删除文章失败')
2026-01-15 13:51:44 +08:00
}
} catch (error) {
console.error('Delete post error:', error)
throw error
}
}
2026-01-16 17:03:34 +08:00
// 分类管理API
export const fetchCategories = async (): Promise<Category[]> => {
try {
const response = await fetch(`${API_BASE}/categories`)
if (!response.ok) throw new Error('Failed to fetch categories')
const data = await response.json()
return data.result || []
} catch (error) {
console.error('Fetch categories error:', error)
return []
}
}
export const getAdminCategories = async (): Promise<Category[]> => {
try {
const response = await fetch(`${API_BASE}/admin/categories`, {
headers: getAuthHeaders()
})
if (!response.ok) throw new Error('Failed to fetch admin categories')
const data = await response.json()
return data.result || []
} catch (error) {
console.error('Get admin categories error:', error)
throw error
}
}
export const createCategory = async (data: Omit<Category, 'id' | 'createdAt' | 'updatedAt'>): Promise<void> => {
try {
const response = await fetch(`${API_BASE}/admin/categories`, {
method: 'POST',
headers: getAuthHeaders(),
body: JSON.stringify(data)
})
if (!response.ok) throw new Error('Create category failed')
} catch (error) {
throw error
}
}
export const updateCategory = async (id: number, data: Omit<Category, 'id' | 'createdAt' | 'updatedAt'>): Promise<void> => {
try {
const response = await fetch(`${API_BASE}/admin/categories/${id}`, {
method: 'PUT',
headers: getAuthHeaders(),
body: JSON.stringify(data)
})
if (!response.ok) throw new Error('Update category failed')
} catch (error) {
throw error
}
}
export const deleteCategory = async (id: number): Promise<void> => {
try {
const response = await fetch(`${API_BASE}/admin/categories/${id}`, {
method: 'DELETE',
headers: getAuthHeaders()
})
if (!response.ok) throw new Error('Delete category failed')
} catch (error) {
throw error
}
}
// 专栏管理API
export const fetchColumns = async (): Promise<Column[]> => {
try {
const response = await fetch(`${API_BASE}/columns`)
if (!response.ok) throw new Error('Failed to fetch columns')
const data = await response.json()
return data.result || []
} catch (error) {
return []
}
}
export const fetchColumn = async (id: number): Promise<Column> => {
try {
const response = await fetch(`${API_BASE}/columns/${id}`)
if (!response.ok) throw new Error('Failed to fetch column')
const data = await response.json()
return data.result
} catch (error) {
throw error
}
}
export const getAdminColumns = async (): Promise<Column[]> => {
try {
const response = await fetch(`${API_BASE}/admin/columns`, {
headers: getAuthHeaders()
})
if (!response.ok) throw new Error('Failed to fetch admin columns')
const data = await response.json()
return data.result || []
} catch (error) {
throw error
}
}
export const createColumn = async (data: Omit<Column, 'id' | 'createdAt' | 'updatedAt'>): Promise<void> => {
try {
const response = await fetch(`${API_BASE}/admin/columns`, {
method: 'POST',
headers: getAuthHeaders(),
body: JSON.stringify(data)
})
if (!response.ok) throw new Error('Create column failed')
} catch (error) {
throw error
}
}
export const updateColumn = async (id: number, data: Omit<Column, 'id' | 'createdAt' | 'updatedAt'>): Promise<void> => {
try {
const response = await fetch(`${API_BASE}/admin/columns/${id}`, {
method: 'PUT',
headers: getAuthHeaders(),
body: JSON.stringify(data)
})
if (!response.ok) throw new Error('Update column failed')
} catch (error) {
throw error
}
}
export const deleteColumn = async (id: number): Promise<void> => {
try {
const response = await fetch(`${API_BASE}/admin/columns/${id}`, {
method: 'DELETE',
headers: getAuthHeaders()
})
if (!response.ok) throw new Error('Delete column failed')
} catch (error) {
throw error
}
}
export const fetchColumnPosts = async (id: number): Promise<Post[]> => {
try {
const response = await fetch(`${API_BASE}/columns/${id}/posts`)
if (!response.ok) throw new Error('Failed to fetch column posts')
const data = await response.json()
return data.result || []
} catch (error) {
console.error('Fetch column posts error:', error)
return []
}
}
export const addPostToColumn = async (columnId: number, postId: number): Promise<void> => {
try {
const response = await fetch(`${API_BASE}/admin/columns/${columnId}/posts`, {
method: 'POST',
headers: getAuthHeaders(),
body: JSON.stringify({ postId })
})
if (!response.ok) throw new Error('Add post to column failed')
} catch (error) {
throw error
}
}
export const removePostFromColumn = async (columnId: number, postId: number): Promise<void> => {
try {
const response = await fetch(`${API_BASE}/admin/columns/${columnId}/posts/${postId}`, {
method: 'DELETE',
headers: getAuthHeaders()
})
if (!response.ok) throw new Error('Remove post from column failed')
} catch (error) {
throw error
}
}
// 标签管理API (复用现有 Tag 类型)
export const fetchTags = async (): Promise<Tag[]> => {
try {
const response = await fetch(`${API_BASE}/tags`)
if (!response.ok) throw new Error('Failed to fetch tags')
const data = await response.json()
return data.result || []
} catch (error) {
return []
}
}
export const adminGetTags = async (): Promise<Tag[]> => {
try {
const response = await fetch(`${API_BASE}/admin/tags`, {
headers: getAuthHeaders()
})
if (!response.ok) throw new Error('Failed to fetch admin tags')
const data = await response.json()
return data.result || []
} catch (error) {
throw error
}
}
export const adminGetTag = async (id: number): Promise<Tag> => {
try {
const response = await fetch(`${API_BASE}/admin/tags/${id}`, {
headers: getAuthHeaders()
})
if (!response.ok) throw new Error('Failed to fetch admin tag')
const data = await response.json()
return data.result // Adapt to standard response
} catch (error) {
throw error
}
}
export const createTag = async (data: { name: string; slug: string }): Promise<void> => {
try {
const response = await fetch(`${API_BASE}/admin/tags`, {
method: 'POST',
headers: getAuthHeaders(),
body: JSON.stringify(data)
})
if (!response.ok) throw new Error('Create tag failed')
} catch (error) {
throw error
}
}
export const updateTag = async (id: number, data: { name: string; slug: string }): Promise<void> => {
try {
const response = await fetch(`${API_BASE}/admin/tags/${id}`, {
method: 'PUT',
headers: getAuthHeaders(),
body: JSON.stringify(data)
})
if (!response.ok) throw new Error('Update tag failed')
} catch (error) {
throw error
}
}
export const deleteTag = async (id: number): Promise<void> => {
try {
const response = await fetch(`${API_BASE}/admin/tags/${id}`, {
method: 'DELETE',
headers: getAuthHeaders()
})
if (!response.ok) throw new Error('Delete tag failed')
} catch (error) {
throw error
}
}
2026-01-15 13:51:44 +08:00
// 文章历史记录API
2026-01-15 17:03:59 +08:00
export const getPostHistory = async (postId: number | string): Promise<PostHistory[]> => {
2026-01-15 13:51:44 +08:00
try {
const response = await fetch(`${API_BASE}/admin/posts/${postId}/history`, {
headers: getAuthHeaders()
})
if (!response.ok) {
const errorData = await response.json()
2026-01-16 17:03:34 +08:00
throw new Error(errorData.message || '获取文章历史失败')
2026-01-15 13:51:44 +08:00
}
2026-01-16 17:03:34 +08:00
const data = await response.json()
return data.result || []
2026-01-15 13:51:44 +08:00
} catch (error) {
console.error('Get post history error:', error)
throw error
}
}
2026-01-15 17:03:59 +08:00
export const getPostHistoryByVersion = async (postId: number | string, version: number): Promise<PostHistory> => {
2026-01-15 13:51:44 +08:00
try {
const response = await fetch(`${API_BASE}/admin/posts/${postId}/history/${version}`, {
headers: getAuthHeaders()
})
if (!response.ok) {
const errorData = await response.json()
2026-01-16 17:03:34 +08:00
throw new Error(errorData.message || '获取指定版本文章历史失败')
2026-01-15 13:51:44 +08:00
}
2026-01-16 17:03:34 +08:00
const data = await response.json()
return data.result
2026-01-15 13:51:44 +08:00
} catch (error) {
console.error('Get post history by version error:', error)
throw error
}
}
// 代码片段管理API
export const getAdminSnippets = async (): Promise<Snippet[]> => {
try {
const response = await fetch(`${API_BASE}/admin/snippets`, {
headers: getAuthHeaders()
})
if (!response.ok) {
const errorData = await response.json()
2026-01-16 17:03:34 +08:00
throw new Error(errorData.message || '获取代码片段列表失败')
2026-01-15 13:51:44 +08:00
}
2026-01-16 17:03:34 +08:00
const data = await response.json()
// 后端返回的是分页格式 {list, total, page, size},需要从 result.list 中取值
return (data.result?.list || []) as Snippet[]
2026-01-15 13:51:44 +08:00
} catch (error) {
console.error('Get admin snippets error:', error)
throw error
}
}
export const fetchSnippets = async (): Promise<Snippet[]> => {
try {
const response = await fetch(`${API_BASE}/snippets`)
if (!response.ok) throw new Error('Failed to fetch snippets')
2026-01-16 17:03:34 +08:00
const data = await response.json()
return data.result || []
2026-01-15 13:51:44 +08:00
} catch (error) {
console.error('Error fetching snippets:', error)
return []
}
}
export const fetchSnippet = async (id: string): Promise<Snippet> => {
try {
const response = await fetch(`${API_BASE}/snippets/${id}`)
if (!response.ok) throw new Error('Failed to fetch snippet')
2026-01-16 17:03:34 +08:00
const data = await response.json()
return data.result
2026-01-15 13:51:44 +08:00
} catch (error) {
console.error(`Error fetching snippet ${id}:`, error)
return {
id: id,
title: '默认代码片段',
code: 'console.log("Hello World");',
type: 'js'
}
}
}
export const createSnippet = async (snippetData: Omit<Snippet, 'id' | 'viewCount'>): Promise<void> => {
try {
const response = await fetch(`${API_BASE}/admin/snippets`, {
method: 'POST',
headers: getAuthHeaders(),
body: JSON.stringify(snippetData)
})
if (!response.ok) {
const errorData = await response.json()
2026-01-16 17:03:34 +08:00
throw new Error(errorData.message || '创建代码片段失败')
2026-01-15 13:51:44 +08:00
}
} catch (error) {
console.error('Create snippet error:', error)
throw error
}
}
export const updateSnippet = async (id: string, snippetData: Omit<Snippet, 'id' | 'viewCount'>): Promise<void> => {
try {
const response = await fetch(`${API_BASE}/admin/snippets/${id}`, {
method: 'PUT',
headers: getAuthHeaders(),
body: JSON.stringify(snippetData)
})
if (!response.ok) {
const errorData = await response.json()
2026-01-16 17:03:34 +08:00
throw new Error(errorData.message || '更新代码片段失败')
2026-01-15 13:51:44 +08:00
}
} catch (error) {
console.error('Update snippet error:', error)
throw error
}
}
export const deleteSnippet = async (id: string): Promise<void> => {
try {
const response = await fetch(`${API_BASE}/admin/snippets/${id}`, {
method: 'DELETE',
headers: getAuthHeaders()
})
if (!response.ok) {
const errorData = await response.json()
2026-01-16 17:03:34 +08:00
throw new Error(errorData.message || '删除代码片段失败')
2026-01-15 13:51:44 +08:00
}
} catch (error) {
console.error('Delete snippet error:', error)
throw error
}
}
// 系统配置API
export const getSettings = async (): Promise<Setting[]> => {
try {
const response = await fetch(`${API_BASE}/admin/settings`, {
headers: getAuthHeaders()
})
if (!response.ok) {
const errorData = await response.json()
2026-01-16 17:03:34 +08:00
throw new Error(errorData.message || '获取系统配置失败')
}
const data = await response.json()
// 确保从 result 字段取值,并确保始终返回数组
if (!data.result) {
return []
2026-01-15 13:51:44 +08:00
}
2026-01-16 17:03:34 +08:00
return Array.isArray(data.result) ? data.result : []
2026-01-15 13:51:44 +08:00
} catch (error) {
console.error('Get settings error:', error)
throw error
}
}
export const createSetting = async (settingData: Omit<Setting, 'id' | 'createdAt' | 'updatedAt'>): Promise<void> => {
try {
const response = await fetch(`${API_BASE}/admin/settings`, {
method: 'POST',
headers: getAuthHeaders(),
body: JSON.stringify(settingData)
})
if (!response.ok) {
const errorData = await response.json()
2026-01-16 17:03:34 +08:00
throw new Error(errorData.message || '创建系统配置失败')
2026-01-15 13:51:44 +08:00
}
} catch (error) {
console.error('Create setting error:', error)
throw error
}
}
export const updateSetting = async (settingData: Omit<Setting, 'createdAt' | 'updatedAt'>): Promise<void> => {
try {
const response = await fetch(`${API_BASE}/admin/settings`, {
method: 'PUT',
headers: getAuthHeaders(),
body: JSON.stringify(settingData)
})
if (!response.ok) {
const errorData = await response.json()
2026-01-16 17:03:34 +08:00
throw new Error(errorData.message || '更新系统配置失败')
2026-01-15 13:51:44 +08:00
}
} catch (error) {
console.error('Update setting error:', error)
throw error
}
}
export const deleteSetting = async (keyName: string): Promise<void> => {
try {
const response = await fetch(`${API_BASE}/admin/settings/${keyName}`, {
method: 'DELETE',
headers: getAuthHeaders()
})
if (!response.ok) {
const errorData = await response.json()
2026-01-16 17:03:34 +08:00
throw new Error(errorData.message || '删除系统配置失败')
2026-01-15 13:51:44 +08:00
}
} catch (error) {
console.error('Delete setting error:', error)
throw error
}
}
2026-01-20 11:12:01 +08:00
// 公开设置API前端使用无需认证
export interface PublicSettings {
site_title?: string
site_description?: string
site_author?: string
site_keywords?: string
2026-01-20 12:02:01 +08:00
visible_menus?: string
2026-01-20 11:12:01 +08:00
}
export const getPublicSettings = async (): Promise<PublicSettings> => {
try {
const response = await fetch(`${API_BASE}/settings`)
if (!response.ok) {
const errorData = await response.json()
throw new Error(errorData.message || '获取网站配置失败')
}
const data = await response.json()
return data.result || {}
} catch (error) {
console.error('Get public settings error:', error)
// 返回空对象,前端使用默认值
return {}
}
}
2026-01-15 13:51:44 +08:00
// 操作日志API
export const getOperationLogs = async (page: number = 1, pageSize: number = 10): Promise<PaginationResponse<OperationLog>> => {
try {
const response = await fetch(`${API_BASE}/admin/operation-logs?page=${page}&pageSize=${pageSize}`, {
headers: getAuthHeaders()
})
if (!response.ok) {
const errorData = await response.json()
2026-01-16 17:03:34 +08:00
throw new Error(errorData.message || '获取操作日志失败')
2026-01-15 13:51:44 +08:00
}
2026-01-16 17:03:34 +08:00
const data = await response.json()
return data.result
2026-01-15 13:51:44 +08:00
} catch (error) {
console.error('Get operation logs error:', error)
throw error
}
}
2026-01-20 11:00:42 +08:00
// 访问日志类型
export interface AccessLog {
id: number
ip: string
userAgent: string
path: string
method: string
statusCode: number
responseTime: number
region: string
createdAt: string
}
// 访问日志API
export const getAccessLogs = async (page: number = 1, pageSize: number = 10): Promise<PaginationResponse<AccessLog>> => {
try {
const response = await fetch(`${API_BASE}/admin/access-logs?page=${page}&pageSize=${pageSize}`, {
headers: getAuthHeaders()
})
if (!response.ok) {
const errorData = await response.json()
throw new Error(errorData.message || '获取访问日志失败')
}
const data = await response.json()
return data.result
} catch (error) {
console.error('Get access logs error:', error)
throw error
}
}
2026-01-20 15:23:37 +08:00
// 文章访问记录类型(来自 user_access_logs 表)
export interface PostAccessLog {
id: number
userId: number
ip: string
region: string
articleId: number
createdAt: string
}
2026-01-20 11:00:42 +08:00
// 获取指定文章的访问记录
2026-01-20 15:23:37 +08:00
export const getPostAccessLogs = async (postId: number, page: number = 1, pageSize: number = 20): Promise<PaginationResponse<PostAccessLog>> => {
2026-01-20 11:00:42 +08:00
try {
const response = await fetch(`${API_BASE}/admin/posts/${postId}/access-logs?page=${page}&pageSize=${pageSize}`, {
headers: getAuthHeaders()
})
if (!response.ok) {
const errorData = await response.json()
throw new Error(errorData.message || '获取文章访问记录失败')
}
const data = await response.json()
return data.result
} catch (error) {
console.error('Get post access logs error:', error)
throw error
}
}
2026-01-15 13:51:44 +08:00
// 仪表盘数据类型
export interface DashboardStats {
users: number
posts: number
works: number
snippets: number
}
// 最近活动类型
export interface RecentActivity {
id: number
icon: string
text: string
time: string
}
// 仪表盘API
2026-01-16 10:19:30 +08:00
export const getDashboardStats = async (startDate?: string, endDate?: string): Promise<DashboardStats> => {
2026-01-15 13:51:44 +08:00
try {
2026-01-16 10:19:30 +08:00
let url = `${API_BASE}/admin/dashboard/stats`
const params = new URLSearchParams()
if (startDate) params.append('startDate', startDate)
if (endDate) params.append('endDate', endDate)
if (params.toString()) url += `?${params.toString()}`
const response = await fetch(url, {
2026-01-15 13:51:44 +08:00
headers: getAuthHeaders()
})
if (!response.ok) {
const errorData = await response.json()
2026-01-16 17:03:34 +08:00
throw new Error(errorData.message || '获取仪表盘统计数据失败')
2026-01-15 13:51:44 +08:00
}
2026-01-16 10:19:30 +08:00
const data = await response.json()
2026-01-16 17:03:34 +08:00
return data.result
2026-01-15 13:51:44 +08:00
} catch (error) {
console.error('Get dashboard stats error:', error)
throw error
}
}
// 获取最近活动
export const getRecentActivities = async (): Promise<RecentActivity[]> => {
try {
const response = await fetch(`${API_BASE}/admin/dashboard/activities`, {
headers: getAuthHeaders()
})
if (!response.ok) {
const errorData = await response.json()
2026-01-16 17:03:34 +08:00
throw new Error(errorData.message || '获取最近活动失败')
2026-01-15 13:51:44 +08:00
}
2026-01-16 17:03:34 +08:00
const data = await response.json()
return data.result || []
2026-01-15 13:51:44 +08:00
} catch (error) {
console.error('Get recent activities error:', error)
throw error
}
}
2026-01-15 15:37:34 +08:00
// 关于页面相关类型
export interface Experience {
year: string
role: string
company: string
}
export interface AboutProfile {
id: number
name: string
avatar: string
location: string
bio: string
email: string
wechat: string
techStack: string[]
experiences: Experience[]
isPrimary: boolean
createdAt: string
updatedAt: string
}
// 关于页面API
export const fetchAboutProfile = async (): Promise<AboutProfile> => {
try {
const response = await fetch(`${API_BASE}/about`)
if (!response.ok) {
const errorData = await response.json()
2026-01-16 17:03:34 +08:00
throw new Error(errorData.message || '获取个人资料失败')
}
const data = await response.json()
// 确保从 result 字段取值
if (!data.result) {
throw new Error('个人资料数据为空')
}
const result = data.result as AboutProfile
// 确保 techStack 和 experiences 始终是数组
if (!Array.isArray(result.techStack)) {
result.techStack = []
}
if (!Array.isArray(result.experiences)) {
result.experiences = []
2026-01-15 15:37:34 +08:00
}
2026-01-16 17:03:34 +08:00
return result
2026-01-15 15:37:34 +08:00
} catch (error) {
console.error('Fetch about profile error:', error)
throw error
}
}
2026-01-15 15:42:20 +08:00
export const getAdminAboutProfiles = async (): Promise<AboutProfile[]> => {
try {
const response = await fetch(`${API_BASE}/admin/about`, {
headers: getAuthHeaders()
})
if (!response.ok) {
const errorData = await response.json()
2026-01-16 17:03:34 +08:00
throw new Error(errorData.message || '获取个人资料列表失败')
2026-01-15 15:42:20 +08:00
}
2026-01-16 17:03:34 +08:00
const data = await response.json()
return data.result || []
2026-01-15 15:42:20 +08:00
} catch (error) {
console.error('Get admin about profiles error:', error)
throw error
}
}
export const createAboutProfile = async (profileData: Omit<AboutProfile, 'id' | 'createdAt' | 'updatedAt'>): Promise<void> => {
try {
const response = await fetch(`${API_BASE}/admin/about`, {
method: 'POST',
headers: getAuthHeaders(),
body: JSON.stringify(profileData)
})
if (!response.ok) {
const errorData = await response.json()
2026-01-16 17:03:34 +08:00
throw new Error(errorData.message || '创建个人资料失败')
2026-01-15 15:42:20 +08:00
}
} catch (error) {
console.error('Create about profile error:', error)
throw error
}
}
export const updateAboutProfile = async (id: number, profileData: Omit<AboutProfile, 'id' | 'createdAt' | 'updatedAt'>): Promise<void> => {
try {
const response = await fetch(`${API_BASE}/admin/about/${id}`, {
method: 'PUT',
headers: getAuthHeaders(),
body: JSON.stringify(profileData)
})
if (!response.ok) {
const errorData = await response.json()
2026-01-16 17:03:34 +08:00
throw new Error(errorData.message || '更新个人资料失败')
2026-01-15 15:42:20 +08:00
}
} catch (error) {
console.error('Update about profile error:', error)
throw error
}
}
export const deleteAboutProfile = async (id: number): Promise<void> => {
try {
const response = await fetch(`${API_BASE}/admin/about/${id}`, {
method: 'DELETE',
headers: getAuthHeaders()
})
if (!response.ok) {
const errorData = await response.json()
2026-01-16 17:03:34 +08:00
throw new Error(errorData.message || '删除个人资料失败')
2026-01-15 15:42:20 +08:00
}
} catch (error) {
console.error('Delete about profile error:', error)
throw error
}
}
2026-01-16 08:29:57 +08:00
// 客户评价相关类型
export interface Testimonial {
id: number
content: string
author: string
role: string
avatar: string
rating: number
createdAt: string
updatedAt: string
}
// 合作伙伴相关类型
export interface Partner {
id: number
name: string
logo: string
description: string
website: string
createdAt: string
updatedAt: string
}
// 客户评价API
export const fetchTestimonials = async (): Promise<Testimonial[]> => {
try {
const response = await fetch(`${API_BASE}/testimonials`)
if (!response.ok) {
const errorData = await response.json()
2026-01-16 17:03:34 +08:00
throw new Error(errorData.message || '获取客户评价失败')
2026-01-16 08:29:57 +08:00
}
2026-01-16 17:03:34 +08:00
const data = await response.json()
return data.result || []
2026-01-16 08:29:57 +08:00
} catch (error) {
console.error('Fetch testimonials error:', error)
throw error
}
}
export const createTestimonial = async (data: Omit<Testimonial, 'id' | 'createdAt' | 'updatedAt'>): Promise<void> => {
try {
const response = await fetch(`${API_BASE}/admin/testimonials`, {
method: 'POST',
headers: getAuthHeaders(),
body: JSON.stringify(data)
})
if (!response.ok) {
const errorData = await response.json()
2026-01-16 17:03:34 +08:00
throw new Error(errorData.message || '创建客户评价失败')
2026-01-16 08:29:57 +08:00
}
} catch (error) {
console.error('Create testimonial error:', error)
throw error
}
}
export const updateTestimonial = async (id: number, data: Omit<Testimonial, 'id' | 'createdAt' | 'updatedAt'>): Promise<void> => {
try {
const response = await fetch(`${API_BASE}/admin/testimonials/${id}`, {
method: 'PUT',
headers: getAuthHeaders(),
body: JSON.stringify(data)
})
if (!response.ok) {
const errorData = await response.json()
2026-01-16 17:03:34 +08:00
throw new Error(errorData.message || '更新客户评价失败')
2026-01-16 08:29:57 +08:00
}
} catch (error) {
console.error('Update testimonial error:', error)
throw error
}
}
export const deleteTestimonial = async (id: number): Promise<void> => {
try {
const response = await fetch(`${API_BASE}/admin/testimonials/${id}`, {
method: 'DELETE',
headers: getAuthHeaders()
})
if (!response.ok) {
const errorData = await response.json()
2026-01-16 17:03:34 +08:00
throw new Error(errorData.message || '删除客户评价失败')
2026-01-16 08:29:57 +08:00
}
} catch (error) {
console.error('Delete testimonial error:', error)
throw error
}
}
// 合作伙伴API
export const fetchPartners = async (): Promise<Partner[]> => {
try {
const response = await fetch(`${API_BASE}/partners`)
if (!response.ok) {
const errorData = await response.json()
2026-01-16 17:03:34 +08:00
throw new Error(errorData.message || '获取合作伙伴失败')
2026-01-16 08:29:57 +08:00
}
2026-01-16 17:03:34 +08:00
const data = await response.json()
return data.result || []
2026-01-16 08:29:57 +08:00
} catch (error) {
console.error('Fetch partners error:', error)
throw error
}
}
export const createPartner = async (data: Omit<Partner, 'id' | 'createdAt' | 'updatedAt'>): Promise<void> => {
try {
const response = await fetch(`${API_BASE}/admin/partners`, {
method: 'POST',
headers: getAuthHeaders(),
body: JSON.stringify(data)
})
if (!response.ok) {
const errorData = await response.json()
2026-01-16 17:03:34 +08:00
throw new Error(errorData.message || '创建合作伙伴失败')
2026-01-16 08:29:57 +08:00
}
} catch (error) {
console.error('Create partner error:', error)
throw error
}
}
export const updatePartner = async (id: number, data: Omit<Partner, 'id' | 'createdAt' | 'updatedAt'>): Promise<void> => {
try {
const response = await fetch(`${API_BASE}/admin/partners/${id}`, {
method: 'PUT',
headers: getAuthHeaders(),
body: JSON.stringify(data)
})
if (!response.ok) {
const errorData = await response.json()
2026-01-16 17:03:34 +08:00
throw new Error(errorData.message || '更新合作伙伴失败')
2026-01-16 08:29:57 +08:00
}
} catch (error) {
console.error('Update partner error:', error)
throw error
}
}
export const deletePartner = async (id: number): Promise<void> => {
try {
const response = await fetch(`${API_BASE}/admin/partners/${id}`, {
method: 'DELETE',
headers: getAuthHeaders()
})
if (!response.ok) {
const errorData = await response.json()
2026-01-16 17:03:34 +08:00
throw new Error(errorData.message || '删除合作伙伴失败')
2026-01-16 08:29:57 +08:00
}
} catch (error) {
console.error('Delete partner error:', error)
throw error
}
}
2026-01-16 09:08:07 +08:00
// 咨询相关类型
export interface Inquiry {
id?: number
name: string
company: string
contactMethod: string
contactValue: string
budget: string
description: string
status?: number // 0-Unread, 1-Read, 2-Contacted
createdAt?: string
}
2026-01-19 16:14:08 +08:00
// OSS配置相关类型
export interface OSSConfig {
2026-01-19 20:21:09 +08:00
id: number
name: string
storageType: string
// 通用字段(向后兼容)
accessKey?: string
secretKey?: string
bucket?: string
region?: string
domain?: string
// 阿里云OSS专用字段
ossAccessKeyId?: string
ossAccessKeySecret?: string
ossEndpoint?: string
ossBucket?: string
ossDomain?: string
// 腾讯云COS专用字段
qcloudSecretId?: string
qcloudSecretKey?: string
qcloudRegion?: string
qcloudBucket?: string
qcloudDomain?: string
// 七牛云专用字段
qiniuAccessKey?: string
qiniuSecretKey?: string
qiniuBucket?: string
qiniuRegion?: string
qiniuDomain?: string
isActive: number
createdAt: string
updatedAt: string
}
// 向后兼容的旧接口定义(已废弃,保留用于类型兼容)
export interface OSSConfigOld {
2026-01-19 16:14:08 +08:00
id: number
name: string
storageType: string // local/qcloud/aliyun/qiniu
accessKey: string // 加密存储,返回时显示为 ***
secretKey: string // 加密存储,返回时显示为 ***
bucket: string
region: string
domain: string
isActive: number
createdAt: string
updatedAt: string
}
2026-01-16 09:08:07 +08:00
export interface EmailSuffix {
id: number
suffix: string
isActive: boolean
sortOrder: number
createdAt: string
updatedAt: string
}
// 咨询相关API
export const submitInquiry = async (data: Inquiry): Promise<void> => {
try {
const response = await fetch(`${API_BASE}/inquiries`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
})
if (!response.ok) {
const errorData = await response.json()
2026-01-16 17:03:34 +08:00
throw new Error(errorData.message || '提交咨询失败')
2026-01-16 09:08:07 +08:00
}
} catch (error) {
console.error('Submit inquiry error:', error)
throw error
}
}
export const fetchEmailSuffixes = async (): Promise<EmailSuffix[]> => {
try {
const response = await fetch(`${API_BASE}/email-suffixes`)
if (!response.ok) {
const errorData = await response.json()
2026-01-16 17:03:34 +08:00
throw new Error(errorData.message || '获取邮箱后缀失败')
2026-01-16 09:08:07 +08:00
}
2026-01-16 17:03:34 +08:00
const data = await response.json()
return data.result || []
2026-01-16 09:08:07 +08:00
} catch (error) {
console.error('Fetch email suffixes error:', error)
throw error
}
}
export const fetchInquiries = async (): Promise<Inquiry[]> => {
try {
const response = await fetch(`${API_BASE}/admin/inquiries`, {
headers: getAuthHeaders()
})
if (!response.ok) {
const errorData = await response.json()
2026-01-16 17:03:34 +08:00
throw new Error(errorData.message || '获取咨询列表失败')
2026-01-16 09:08:07 +08:00
}
2026-01-16 17:03:34 +08:00
const data = await response.json()
return data.result || []
2026-01-16 09:08:07 +08:00
} catch (error) {
console.error('Fetch inquiries error:', error)
throw error
}
}
2026-01-19 16:14:08 +08:00
// OSS配置相关API
export const getOSSConfigs = async (): Promise<OSSConfig[]> => {
try {
const response = await fetch(`${API_BASE}/admin/oss-configs`, {
headers: getAuthHeaders()
})
if (!response.ok) {
const errorData = await response.json()
throw new Error(errorData.message || '获取OSS配置失败')
}
const data = await response.json()
return data.result || []
} catch (error) {
console.error('Get OSS configs error:', error)
throw error
}
}
export const createOSSConfig = async (configData: Omit<OSSConfig, 'id' | 'createdAt' | 'updatedAt'>): Promise<OSSConfig> => {
try {
const response = await fetch(`${API_BASE}/admin/oss-configs`, {
method: 'POST',
headers: getAuthHeaders(),
body: JSON.stringify(configData)
})
if (!response.ok) {
const errorData = await response.json()
throw new Error(errorData.message || '创建OSS配置失败')
}
const data = await response.json()
return data.result
} catch (error) {
console.error('Create OSS config error:', error)
throw error
}
}
export const updateOSSConfig = async (id: number, configData: Partial<Omit<OSSConfig, 'id' | 'createdAt' | 'updatedAt'>>): Promise<OSSConfig> => {
try {
const response = await fetch(`${API_BASE}/admin/oss-configs/${id}`, {
method: 'PUT',
headers: getAuthHeaders(),
body: JSON.stringify(configData)
})
if (!response.ok) {
const errorData = await response.json()
throw new Error(errorData.message || '更新OSS配置失败')
}
const data = await response.json()
return data.result
} catch (error) {
console.error('Update OSS config error:', error)
throw error
}
}
export const deleteOSSConfig = async (id: number): Promise<void> => {
try {
const response = await fetch(`${API_BASE}/admin/oss-configs/${id}`, {
method: 'DELETE',
headers: getAuthHeaders()
})
if (!response.ok) {
const errorData = await response.json()
throw new Error(errorData.message || '删除OSS配置失败')
}
} catch (error) {
console.error('Delete OSS config error:', error)
throw error
}
}
2026-01-19 20:21:09 +08:00
// 附件相关类型
export interface Attachment {
id: number
categoryId?: number
category?: {
id: number
name: string
}
originalName: string
storedName: string
filePath: string
fileUrl: string
fileSize: number
fileType: string
mimeType: string
storageType: string
ossConfigId?: number
createdAt: string
updatedAt: string
}
// 附件分类相关类型
export interface AttachmentCategory {
id: number
name: string
description: string
sortOrder: number
createdAt: string
updatedAt: string
}
// 附件管理API
2026-01-19 21:19:35 +08:00
export const getAdminAttachments = async (params?: {
page?: number
pageSize?: number
categoryId?: number
fileType?: string
keyword?: string
}): Promise<{ list: Attachment[], total: number, page: number, size: number }> => {
try {
const queryParams = new URLSearchParams()
if (params?.page) queryParams.append('page', params.page.toString())
if (params?.pageSize) queryParams.append('pageSize', params.pageSize.toString())
if (params?.categoryId) queryParams.append('categoryId', params.categoryId.toString())
if (params?.fileType) queryParams.append('fileType', params.fileType)
if (params?.keyword) queryParams.append('keyword', params.keyword)
const url = `${API_BASE}/admin/attachments${queryParams.toString() ? '?' + queryParams.toString() : ''}`
const response = await fetch(url, {
headers: getAuthHeaders()
})
if (!response.ok) {
const errorData = await response.json()
throw new Error(errorData.message || '获取附件列表失败')
}
const data = await response.json()
return {
list: data.result?.list || [],
total: data.result?.total || 0,
page: data.result?.page || 1,
size: data.result?.size || 20
}
} catch (error) {
console.error('Get admin attachments error:', error)
throw error
}
}
2026-01-19 20:21:09 +08:00
export const updateAttachment = async (id: number, data: { categoryId?: number | null }): Promise<Attachment> => {
try {
const response = await fetch(`${API_BASE}/admin/attachments/${id}`, {
method: 'PUT',
headers: getAuthHeaders(),
body: JSON.stringify(data)
})
if (!response.ok) {
const errorData = await response.json()
throw new Error(errorData.message || '更新附件失败')
}
const responseData = await response.json()
return responseData.result
} catch (error) {
console.error('Update attachment error:', error)
throw error
}
}
// 附件分类管理API
export const getAttachmentCategories = async (): Promise<AttachmentCategory[]> => {
try {
const response = await fetch(`${API_BASE}/admin/attachment-categories`, {
headers: getAuthHeaders()
})
if (!response.ok) {
const errorData = await response.json()
throw new Error(errorData.message || '获取附件分类列表失败')
}
const data = await response.json()
return data.result || []
} catch (error) {
console.error('Get attachment categories error:', error)
throw error
}
}
export const createAttachmentCategory = async (categoryData: Omit<AttachmentCategory, 'id' | 'createdAt' | 'updatedAt'>): Promise<void> => {
try {
const response = await fetch(`${API_BASE}/admin/attachment-categories`, {
method: 'POST',
headers: getAuthHeaders(),
body: JSON.stringify(categoryData)
})
if (!response.ok) {
const errorData = await response.json()
throw new Error(errorData.message || '创建附件分类失败')
}
} catch (error) {
console.error('Create attachment category error:', error)
throw error
}
}
export const updateAttachmentCategory = async (id: number, categoryData: Partial<Omit<AttachmentCategory, 'id' | 'createdAt' | 'updatedAt'>>): Promise<void> => {
try {
const response = await fetch(`${API_BASE}/admin/attachment-categories/${id}`, {
method: 'PUT',
headers: getAuthHeaders(),
body: JSON.stringify(categoryData)
})
if (!response.ok) {
const errorData = await response.json()
throw new Error(errorData.message || '更新附件分类失败')
}
} catch (error) {
console.error('Update attachment category error:', error)
throw error
}
}
export const deleteAttachmentCategory = async (id: number): Promise<void> => {
try {
const response = await fetch(`${API_BASE}/admin/attachment-categories/${id}`, {
method: 'DELETE',
headers: getAuthHeaders()
})
if (!response.ok) {
const errorData = await response.json()
throw new Error(errorData.message || '删除附件分类失败')
}
} catch (error) {
console.error('Delete attachment category error:', error)
throw error
}
}