diff --git a/backend/src/main/java/com/innovation/platform/controller/ProjectController.java b/backend/src/main/java/com/innovation/platform/controller/ProjectController.java new file mode 100644 index 0000000..9d604b2 --- /dev/null +++ b/backend/src/main/java/com/innovation/platform/controller/ProjectController.java @@ -0,0 +1,68 @@ +package com.innovation.platform.controller; + +import cn.dev33.satoken.annotation.SaCheckLogin; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.innovation.platform.common.PageResult; +import com.innovation.platform.common.Result; +import com.innovation.platform.dto.ProjectQueryRequest; +import com.innovation.platform.dto.ProjectRequest; +import com.innovation.platform.dto.ProjectResponse; +import com.innovation.platform.service.ProjectService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.*; + +/** + * 项目管理控制器 + */ +@Tag(name = "项目管理", description = "项目的增删改查接口") +@RestController +@RequestMapping("/api/projects") +@RequiredArgsConstructor +@SaCheckLogin +public class ProjectController { + + private final ProjectService projectService; + + @Operation(summary = "分页查询项目列表") + @GetMapping + public Result> page(ProjectQueryRequest request) { + IPage page = projectService.page(request); + return Result.success(PageResult.of(page)); + } + + @Operation(summary = "根据ID查询项目详情") + @GetMapping("/{id}") + public Result getById( + @Parameter(description = "项目ID") @PathVariable Long id) { + ProjectResponse project = projectService.getById(id); + return Result.success(project); + } + + @Operation(summary = "创建项目") + @PostMapping + public Result create(@Valid @RequestBody ProjectRequest request) { + Long id = projectService.create(request); + return Result.success("创建成功", id); + } + + @Operation(summary = "更新项目") + @PutMapping("/{id}") + public Result update( + @Parameter(description = "项目ID") @PathVariable Long id, + @Valid @RequestBody ProjectRequest request) { + projectService.update(id, request); + return Result.success("更新成功", null); + } + + @Operation(summary = "删除项目") + @DeleteMapping("/{id}") + public Result delete( + @Parameter(description = "项目ID") @PathVariable Long id) { + projectService.delete(id); + return Result.success("删除成功", null); + } +} diff --git a/backend/src/main/java/com/innovation/platform/dto/ProjectQueryRequest.java b/backend/src/main/java/com/innovation/platform/dto/ProjectQueryRequest.java new file mode 100644 index 0000000..5500941 --- /dev/null +++ b/backend/src/main/java/com/innovation/platform/dto/ProjectQueryRequest.java @@ -0,0 +1,54 @@ +package com.innovation.platform.dto; + +import lombok.Data; + +/** + * 项目查询请求 DTO + */ +@Data +public class ProjectQueryRequest { + /** + * 项目名称(模糊查询) + */ + private String projectName; + + /** + * 项目类型 + */ + private Integer projectType; + + /** + * 项目级别 + */ + private Integer projectLevel; + + /** + * 项目状态 + */ + private Integer status; + + /** + * 负责人ID + */ + private Long leaderId; + + /** + * 指导老师ID + */ + private Long advisorId; + + /** + * 学院 + */ + private String college; + + /** + * 当前页 + */ + private Integer current = 1; + + /** + * 每页大小 + */ + private Integer size = 10; +} diff --git a/backend/src/main/java/com/innovation/platform/dto/ProjectRequest.java b/backend/src/main/java/com/innovation/platform/dto/ProjectRequest.java new file mode 100644 index 0000000..4197b9d --- /dev/null +++ b/backend/src/main/java/com/innovation/platform/dto/ProjectRequest.java @@ -0,0 +1,64 @@ +package com.innovation.platform.dto; + +import com.innovation.platform.entity.Project; +import lombok.Data; +import java.math.BigDecimal; +import java.time.LocalDate; + +/** + * 项目请求 DTO + */ +@Data +public class ProjectRequest { + private String projectNo; + + private String projectName; + + private Integer projectType; + + private Integer projectLevel; + + private Long leaderId; + + private Long advisorId; + + private String description; + + private String researchPlan; + + private String expectedResult; + + private String budget; + + private Integer status; + + private LocalDate startTime; + + private LocalDate endTime; + + private String college; + + /** + * 转换为实体 + */ + public Project toEntity() { + Project project = new Project(); + project.setProjectNo(this.projectNo); + project.setProjectName(this.projectName); + project.setProjectType(this.projectType); + project.setProjectLevel(this.projectLevel); + project.setLeaderId(this.leaderId); + project.setAdvisorId(this.advisorId); + project.setDescription(this.description); + project.setResearchPlan(this.researchPlan); + project.setExpectedResult(this.expectedResult); + if (this.budget != null && !this.budget.isEmpty()) { + project.setBudget(new BigDecimal(this.budget)); + } + project.setStatus(this.status); + project.setStartTime(this.startTime); + project.setEndTime(this.endTime); + project.setCollege(this.college); + return project; + } +} diff --git a/backend/src/main/java/com/innovation/platform/dto/ProjectResponse.java b/backend/src/main/java/com/innovation/platform/dto/ProjectResponse.java new file mode 100644 index 0000000..f6bfbeb --- /dev/null +++ b/backend/src/main/java/com/innovation/platform/dto/ProjectResponse.java @@ -0,0 +1,60 @@ +package com.innovation.platform.dto; + +import com.innovation.platform.entity.Project; +import lombok.Builder; +import lombok.Data; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; + +/** + * 项目响应 DTO + */ +@Data +@Builder +public class ProjectResponse { + private Long id; + private String projectNo; + private String projectName; + private Integer projectType; + private Integer projectLevel; + private Long leaderId; + private String leaderName; + private Long advisorId; + private String advisorName; + private String description; + private String researchPlan; + private String expectedResult; + private BigDecimal budget; + private Integer status; + private LocalDate startTime; + private LocalDate endTime; + private String college; + private LocalDateTime createTime; + private LocalDateTime updateTime; + + /** + * 从实体转换 + */ + public static ProjectResponse fromEntity(Project project) { + return ProjectResponse.builder() + .id(project.getId()) + .projectNo(project.getProjectNo()) + .projectName(project.getProjectName()) + .projectType(project.getProjectType()) + .projectLevel(project.getProjectLevel()) + .leaderId(project.getLeaderId()) + .advisorId(project.getAdvisorId()) + .description(project.getDescription()) + .researchPlan(project.getResearchPlan()) + .expectedResult(project.getExpectedResult()) + .budget(project.getBudget()) + .status(project.getStatus()) + .startTime(project.getStartTime()) + .endTime(project.getEndTime()) + .college(project.getCollege()) + .createTime(project.getCreateTime()) + .updateTime(project.getUpdateTime()) + .build(); + } +} diff --git a/backend/src/main/java/com/innovation/platform/mapper/ProjectMapper.java b/backend/src/main/java/com/innovation/platform/mapper/ProjectMapper.java new file mode 100644 index 0000000..e10eb2c --- /dev/null +++ b/backend/src/main/java/com/innovation/platform/mapper/ProjectMapper.java @@ -0,0 +1,12 @@ +package com.innovation.platform.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.innovation.platform.entity.Project; +import org.apache.ibatis.annotations.Mapper; + +/** + * 项目 Mapper 接口 + */ +@Mapper +public interface ProjectMapper extends BaseMapper { +} diff --git a/backend/src/main/java/com/innovation/platform/service/ProjectService.java b/backend/src/main/java/com/innovation/platform/service/ProjectService.java new file mode 100644 index 0000000..2ac9fa2 --- /dev/null +++ b/backend/src/main/java/com/innovation/platform/service/ProjectService.java @@ -0,0 +1,43 @@ +package com.innovation.platform.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.innovation.platform.dto.ProjectQueryRequest; +import com.innovation.platform.dto.ProjectRequest; +import com.innovation.platform.dto.ProjectResponse; +import com.innovation.platform.entity.Project; + +/** + * 项目服务接口 + */ +public interface ProjectService { + + /** + * 分页查询项目列表 + */ + IPage page(ProjectQueryRequest request); + + /** + * 根据ID查询项目详情 + */ + ProjectResponse getById(Long id); + + /** + * 创建项目 + */ + Long create(ProjectRequest request); + + /** + * 更新项目 + */ + void update(Long id, ProjectRequest request); + + /** + * 删除项目 + */ + void delete(Long id); + + /** + * 获取项目实体 + */ + Project getEntityById(Long id); +} diff --git a/backend/src/main/java/com/innovation/platform/service/impl/ProjectServiceImpl.java b/backend/src/main/java/com/innovation/platform/service/impl/ProjectServiceImpl.java new file mode 100644 index 0000000..ebfa6b7 --- /dev/null +++ b/backend/src/main/java/com/innovation/platform/service/impl/ProjectServiceImpl.java @@ -0,0 +1,107 @@ +package com.innovation.platform.service.impl; + +import cn.dev33.satoken.stp.StpUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.innovation.platform.dto.ProjectQueryRequest; +import com.innovation.platform.dto.ProjectRequest; +import com.innovation.platform.dto.ProjectResponse; +import com.innovation.platform.entity.Project; +import com.innovation.platform.mapper.ProjectMapper; +import com.innovation.platform.service.ProjectService; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.StringUtils; + +/** + * 项目服务实现类 + */ +@Service +@RequiredArgsConstructor +public class ProjectServiceImpl implements ProjectService { + + private final ProjectMapper projectMapper; + + @Override + public IPage page(ProjectQueryRequest request) { + Page page = new Page<>(request.getCurrent(), request.getSize()); + + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.like(StringUtils.hasText(request.getProjectName()), Project::getProjectName, request.getProjectName()) + .eq(request.getProjectType() != null, Project::getProjectType, request.getProjectType()) + .eq(request.getProjectLevel() != null, Project::getProjectLevel, request.getProjectLevel()) + .eq(request.getStatus() != null, Project::getStatus, request.getStatus()) + .eq(request.getLeaderId() != null, Project::getLeaderId, request.getLeaderId()) + .eq(request.getAdvisorId() != null, Project::getAdvisorId, request.getAdvisorId()) + .eq(StringUtils.hasText(request.getCollege()), Project::getCollege, request.getCollege()) + .orderByDesc(Project::getCreateTime); + + IPage projectPage = projectMapper.selectPage(page, wrapper); + + return projectPage.convert(ProjectResponse::fromEntity); + } + + @Override + public ProjectResponse getById(Long id) { + Project project = projectMapper.selectById(id); + if (project == null) { + throw new RuntimeException("项目不存在"); + } + return ProjectResponse.fromEntity(project); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public Long create(ProjectRequest request) { + Project project = request.toEntity(); + project.setStatus(project.getStatus() != null ? project.getStatus() : 0); + + // 设置创建人 + Long userId = StpUtil.getLoginIdAsLong(); + project.setCreateBy(userId); + project.setUpdateBy(userId); + + projectMapper.insert(project); + return project.getId(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void update(Long id, ProjectRequest request) { + Project existingProject = projectMapper.selectById(id); + if (existingProject == null) { + throw new RuntimeException("项目不存在"); + } + + Project project = request.toEntity(); + project.setId(id); + + // 设置更新人 + Long userId = StpUtil.getLoginIdAsLong(); + project.setUpdateBy(userId); + + // 保留原有的创建信息 + project.setCreateBy(existingProject.getCreateBy()); + project.setCreateTime(existingProject.getCreateTime()); + + projectMapper.updateById(project); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void delete(Long id) { + Project project = projectMapper.selectById(id); + if (project == null) { + throw new RuntimeException("项目不存在"); + } + projectMapper.deleteById(id); + } + + @Override + public Project getEntityById(Long id) { + return projectMapper.selectById(id); + } +}