feat: 添加项目管理模块

- 新增 ProjectMapper 接口
- 新增 ProjectService 服务接口及实现
- 新增 ProjectController 控制器
- 新增 DTO: ProjectRequest, ProjectResponse, ProjectQueryRequest
- API 接口: 项目列表(分页)、项目详情、创建、更新、删除
This commit is contained in:
likingcode
2026-03-02 00:43:17 +00:00
parent 95d1b5e070
commit 3953488231
7 changed files with 408 additions and 0 deletions

View File

@@ -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<PageResult<ProjectResponse>> page(ProjectQueryRequest request) {
IPage<ProjectResponse> page = projectService.page(request);
return Result.success(PageResult.of(page));
}
@Operation(summary = "根据ID查询项目详情")
@GetMapping("/{id}")
public Result<ProjectResponse> getById(
@Parameter(description = "项目ID") @PathVariable Long id) {
ProjectResponse project = projectService.getById(id);
return Result.success(project);
}
@Operation(summary = "创建项目")
@PostMapping
public Result<Long> create(@Valid @RequestBody ProjectRequest request) {
Long id = projectService.create(request);
return Result.success("创建成功", id);
}
@Operation(summary = "更新项目")
@PutMapping("/{id}")
public Result<Void> 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<Void> delete(
@Parameter(description = "项目ID") @PathVariable Long id) {
projectService.delete(id);
return Result.success("删除成功", null);
}
}

View File

@@ -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;
}

View File

@@ -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;
}
}

View File

@@ -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();
}
}

View File

@@ -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<Project> {
}

View File

@@ -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<ProjectResponse> 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);
}

View File

@@ -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<ProjectResponse> page(ProjectQueryRequest request) {
Page<Project> page = new Page<>(request.getCurrent(), request.getSize());
LambdaQueryWrapper<Project> 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<Project> 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);
}
}