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
98 lines
2.6 KiB
TypeScript
98 lines
2.6 KiB
TypeScript
import { create } from 'zustand';
|
|
import { projectApi } from '../api/projectApi';
|
|
import { message } from 'antd';
|
|
|
|
export interface Project {
|
|
id: string;
|
|
name: string;
|
|
background: string;
|
|
researchType: 'observational' | 'interventional';
|
|
createdAt: string;
|
|
updatedAt: string;
|
|
}
|
|
|
|
interface ProjectState {
|
|
// 当前选中的项目
|
|
currentProject: Project | null;
|
|
|
|
// 所有项目列表
|
|
projects: Project[];
|
|
|
|
// 加载状态
|
|
loading: boolean;
|
|
|
|
// 是否显示创建项目对话框
|
|
showCreateDialog: boolean;
|
|
|
|
// 是否显示编辑项目对话框
|
|
showEditDialog: boolean;
|
|
|
|
// Actions
|
|
setCurrentProject: (project: Project | null) => void;
|
|
setProjects: (projects: Project[]) => void;
|
|
addProject: (project: Project) => void;
|
|
updateProject: (id: string, updates: Partial<Project>) => void;
|
|
deleteProject: (id: string) => void;
|
|
setShowCreateDialog: (show: boolean) => void;
|
|
setShowEditDialog: (show: boolean) => void;
|
|
setLoading: (loading: boolean) => void;
|
|
fetchProjects: () => Promise<void>;
|
|
}
|
|
|
|
export const useProjectStore = create<ProjectState>((set) => ({
|
|
currentProject: null,
|
|
projects: [],
|
|
loading: false,
|
|
showCreateDialog: false,
|
|
showEditDialog: false,
|
|
|
|
setCurrentProject: (project) => set({ currentProject: project }),
|
|
|
|
setProjects: (projects) => set({ projects }),
|
|
|
|
addProject: (project) => set((state) => ({
|
|
projects: [...state.projects, project],
|
|
})),
|
|
|
|
updateProject: (id, updates) => set((state) => ({
|
|
projects: state.projects.map((p) =>
|
|
p.id === id ? { ...p, ...updates } : p
|
|
),
|
|
currentProject:
|
|
state.currentProject?.id === id
|
|
? { ...state.currentProject, ...updates }
|
|
: state.currentProject,
|
|
})),
|
|
|
|
deleteProject: (id) => set((state) => ({
|
|
projects: state.projects.filter((p) => p.id !== id),
|
|
currentProject:
|
|
state.currentProject?.id === id ? null : state.currentProject,
|
|
})),
|
|
|
|
setShowCreateDialog: (show) => set({ showCreateDialog: show }),
|
|
|
|
setShowEditDialog: (show) => set({ showEditDialog: show }),
|
|
|
|
setLoading: (loading) => set({ loading }),
|
|
|
|
// 获取项目列表
|
|
fetchProjects: async () => {
|
|
try {
|
|
set({ loading: true });
|
|
const response = await projectApi.getProjects();
|
|
if (response.success && response.data) {
|
|
set({ projects: response.data });
|
|
} else {
|
|
message.error(response.message || '获取项目列表失败');
|
|
}
|
|
} catch (error) {
|
|
console.error('获取项目列表失败:', error);
|
|
message.error('获取项目列表失败');
|
|
} finally {
|
|
set({ loading: false });
|
|
}
|
|
},
|
|
}));
|
|
|