Files
photography/admin/src/services/photoService.ts
xujiang 72414d0979 feat: 完成后端-管理后台集成及部署配置
🚀 主要功能:
- 完善后端API服务层,实现完整的CRUD操作
- 开发管理后台所有核心页面 (仪表板、照片、分类、标签、用户、设置)
- 完成前后端完全集成,所有API接口正常对接
- 配置完整的CI/CD流水线,支持自动化部署

🎯 后端完善:
- 实现PhotoService, CategoryService, TagService, UserService
- 添加完整的API处理器和路由配置
- 支持Docker容器化部署
- 添加数据库迁移和健康检查

🎨 管理后台完成:
- 仪表板: 实时统计数据展示
- 照片管理: 完整的CRUD操作,支持批量处理
- 分类管理: 树形结构展示和管理
- 标签管理: 颜色标签和统计信息
- 用户管理: 角色权限控制
- 系统设置: 多标签配置界面
- 添加pre-commit代码质量检查

🔧 部署配置:
- Docker Compose完整配置
- 后端CI/CD流水线 (Docker部署)
- 管理后台CI/CD流水线 (静态文件部署)
- 前端CI/CD流水线优化
- 自动化脚本: 部署、备份、监控
- 完整的部署文档和运维指南

 集成完成:
- 所有API接口正常连接
- 认证系统完整集成
- 数据获取和状态管理
- 错误处理和用户反馈
- 响应式设计优化
2025-07-09 16:23:18 +08:00

184 lines
4.3 KiB
TypeScript

import api from './api'
export interface Photo {
id: number
title: string
description: string
originalFilename: string
uniqueFilename: string
fileSize: number
status: 'draft' | 'published' | 'archived' | 'processing'
camera?: string
lens?: string
iso?: number
aperture?: string
shutterSpeed?: string
focalLength?: string
takenAt?: string
createdAt: string
updatedAt: string
categories: Category[]
tags: Tag[]
formats: PhotoFormat[]
}
export interface PhotoFormat {
id: number
photoId: number
format: string
width: number
height: number
quality: number
fileSize: number
url: string
createdAt: string
}
export interface Category {
id: number
name: string
slug: string
description: string
photoCount: number
}
export interface Tag {
id: number
name: string
slug: string
description: string
color?: string
photoCount: number
}
export interface PhotoListParams {
page?: number
limit?: number
search?: string
status?: string
category_id?: number
tags?: string[]
start_date?: string
end_date?: string
sort_by?: string
sort_order?: string
}
export interface PhotoListResponse {
photos: Photo[]
total: number
page: number
limit: number
pages: number
}
export interface CreatePhotoRequest {
title: string
description?: string
status?: string
categoryIds?: number[]
tagIds?: number[]
camera?: string
lens?: string
iso?: number
aperture?: string
shutterSpeed?: string
focalLength?: string
takenAt?: string
}
export interface UpdatePhotoRequest {
title?: string
description?: string
status?: string
categoryIds?: number[]
tagIds?: number[]
camera?: string
lens?: string
iso?: number
aperture?: string
shutterSpeed?: string
focalLength?: string
takenAt?: string
}
export interface BatchUpdateRequest {
status?: string
categoryIds?: number[]
tagIds?: number[]
}
export interface PhotoStats {
total: number
thisMonth: number
today: number
totalSize: number
statusStats: Record<string, number>
}
class PhotoService {
async getPhotos(params: PhotoListParams = {}): Promise<PhotoListResponse> {
const response = await api.get('/photos', { params })
return response.data
}
async getPhoto(id: number): Promise<Photo> {
const response = await api.get(`/photos/${id}`)
return response.data
}
async createPhoto(data: CreatePhotoRequest): Promise<Photo> {
const response = await api.post('/photos', data)
return response.data
}
async updatePhoto(id: number, data: UpdatePhotoRequest): Promise<Photo> {
const response = await api.put(`/photos/${id}`, data)
return response.data
}
async deletePhoto(id: number): Promise<void> {
await api.delete(`/photos/${id}`)
}
async uploadPhoto(file: File, data: CreatePhotoRequest): Promise<Photo> {
const formData = new FormData()
formData.append('file', file)
// 添加其他字段
if (data.title) formData.append('title', data.title)
if (data.description) formData.append('description', data.description)
if (data.status) formData.append('status', data.status)
if (data.categoryIds) formData.append('category_ids', data.categoryIds.join(','))
if (data.tagIds) formData.append('tag_ids', data.tagIds.join(','))
if (data.camera) formData.append('camera', data.camera)
if (data.lens) formData.append('lens', data.lens)
if (data.iso) formData.append('iso', data.iso.toString())
if (data.aperture) formData.append('aperture', data.aperture)
if (data.shutterSpeed) formData.append('shutter_speed', data.shutterSpeed)
if (data.focalLength) formData.append('focal_length', data.focalLength)
if (data.takenAt) formData.append('taken_at', data.takenAt)
const response = await api.post('/photos/upload', formData, {
headers: {
'Content-Type': 'multipart/form-data',
},
})
return response.data
}
async batchUpdate(ids: number[], data: BatchUpdateRequest): Promise<void> {
await api.post('/photos/batch/update', { ids, ...data })
}
async batchDelete(ids: number[]): Promise<void> {
await api.post('/photos/batch/delete', { ids })
}
async getStats(): Promise<PhotoStats> {
const response = await api.get('/photos/stats')
return response.data
}
}
export const photoService = new PhotoService()