feat: Day 8-9 - Project Management API completed
Backend: - Create project routes (GET, POST, PUT, DELETE) - Implement projectController with CRUD operations - Create projectService for database operations - Add validation middleware for request validation - Update Prisma schema (add background, researchType, deletedAt fields) - Implement soft delete for projects Frontend: - Create projectApi service module - Update useProjectStore with fetchProjects and loading state - Connect ProjectSelector to real API with loading indicator - Connect CreateProjectDialog to real API with error handling - Connect EditProjectDialog to real API with loading state - Add comprehensive error handling and user feedback Build: Both frontend and backend build successfully
This commit is contained in:
102
backend/src/services/projectService.ts
Normal file
102
backend/src/services/projectService.ts
Normal file
@@ -0,0 +1,102 @@
|
||||
import { prisma } from '../config/database.js';
|
||||
|
||||
export interface CreateProjectDTO {
|
||||
name: string;
|
||||
background: string;
|
||||
researchType: 'observational' | 'interventional';
|
||||
userId: string;
|
||||
}
|
||||
|
||||
export interface UpdateProjectDTO {
|
||||
name?: string;
|
||||
background?: string;
|
||||
researchType?: 'observational' | 'interventional';
|
||||
}
|
||||
|
||||
class ProjectService {
|
||||
// 获取用户的所有项目
|
||||
async getProjectsByUserId(userId: string) {
|
||||
return prisma.project.findMany({
|
||||
where: {
|
||||
userId,
|
||||
deletedAt: null,
|
||||
},
|
||||
orderBy: {
|
||||
createdAt: 'desc',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// 根据ID获取项目
|
||||
async getProjectById(projectId: string, userId: string) {
|
||||
return prisma.project.findFirst({
|
||||
where: {
|
||||
id: projectId,
|
||||
userId,
|
||||
deletedAt: null,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// 创建项目
|
||||
async createProject(data: CreateProjectDTO) {
|
||||
return prisma.project.create({
|
||||
data: {
|
||||
name: data.name,
|
||||
background: data.background,
|
||||
researchType: data.researchType,
|
||||
userId: data.userId,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// 更新项目
|
||||
async updateProject(projectId: string, userId: string, data: UpdateProjectDTO) {
|
||||
// 先检查项目是否存在且属于该用户
|
||||
const project = await this.getProjectById(projectId, userId);
|
||||
if (!project) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return prisma.project.update({
|
||||
where: {
|
||||
id: projectId,
|
||||
},
|
||||
data: {
|
||||
...data,
|
||||
updatedAt: new Date(),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// 软删除项目
|
||||
async deleteProject(projectId: string, userId: string) {
|
||||
// 先检查项目是否存在且属于该用户
|
||||
const project = await this.getProjectById(projectId, userId);
|
||||
if (!project) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return prisma.project.update({
|
||||
where: {
|
||||
id: projectId,
|
||||
},
|
||||
data: {
|
||||
deletedAt: new Date(),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// 统计用户的项目数量
|
||||
async countUserProjects(userId: string) {
|
||||
return prisma.project.count({
|
||||
where: {
|
||||
userId,
|
||||
deletedAt: null,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export const projectService = new ProjectService();
|
||||
|
||||
Reference in New Issue
Block a user