diff --git a/agt-module-license/agt-module-license-api/src/main/java/org/agt/module/license/enums/ErrorCodeConstants.java b/agt-module-license/agt-module-license-api/src/main/java/org/agt/module/license/enums/ErrorCodeConstants.java index c61c52b..4bfefd7 100644 --- a/agt-module-license/agt-module-license-api/src/main/java/org/agt/module/license/enums/ErrorCodeConstants.java +++ b/agt-module-license/agt-module-license-api/src/main/java/org/agt/module/license/enums/ErrorCodeConstants.java @@ -11,4 +11,5 @@ public interface ErrorCodeConstants { ErrorCode CUSTOMER_NOT_EXISTS = new ErrorCode(1_100_001_001, "客户不存在"); ErrorCode CUSTOMER_NAME_DUPLICATE = new ErrorCode(1_100_001_002, "客户名称`{}`已存在"); ErrorCode CUSTOMER_CODE_DUPLICATE = new ErrorCode(1_100_001_003, "客户编号`{}`已存在"); + ErrorCode PROJECT_NOT_EXISTS = new ErrorCode(1_100_002_001, "项目不存在"); } diff --git a/agt-module-license/agt-module-license-server/src/main/java/org/agt/module/license/controller/admin/project/ProjectController.java b/agt-module-license/agt-module-license-server/src/main/java/org/agt/module/license/controller/admin/project/ProjectController.java new file mode 100644 index 0000000..777f4bc --- /dev/null +++ b/agt-module-license/agt-module-license-server/src/main/java/org/agt/module/license/controller/admin/project/ProjectController.java @@ -0,0 +1,95 @@ +package org.agt.module.license.controller.admin.project; + +import org.springframework.web.bind.annotation.*; +import jakarta.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.security.access.prepost.PreAuthorize; +import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Operation; + +import jakarta.validation.constraints.*; +import jakarta.validation.*; +import jakarta.servlet.http.*; +import java.util.*; +import java.io.IOException; + +import org.agt.framework.common.pojo.PageParam; +import org.agt.framework.common.pojo.PageResult; +import org.agt.framework.common.pojo.CommonResult; +import org.agt.framework.common.util.object.BeanUtils; +import static org.agt.framework.common.pojo.CommonResult.success; + +import org.agt.framework.excel.core.util.ExcelUtils; + +import org.agt.framework.apilog.core.annotation.ApiAccessLog; +import static org.agt.framework.apilog.core.enums.OperateTypeEnum.*; + +import org.agt.module.license.controller.admin.project.vo.*; +import org.agt.module.license.dal.dataobject.project.ProjectDO; +import org.agt.module.license.service.project.ProjectService; + +@Tag(name = "管理后台 - 项目") +@RestController +@RequestMapping("/license/project") +@Validated +public class ProjectController { + + @Resource + private ProjectService projectService; + + @PostMapping("/create") + @Operation(summary = "创建项目") + @PreAuthorize("@ss.hasPermission('license:project:create')") + public CommonResult createProject(@Valid @RequestBody ProjectSaveReqVO createReqVO) { + return success(projectService.createProject(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新项目") + @PreAuthorize("@ss.hasPermission('license:project:update')") + public CommonResult updateProject(@Valid @RequestBody ProjectSaveReqVO updateReqVO) { + projectService.updateProject(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除项目") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('license:project:delete')") + public CommonResult deleteProject(@RequestParam("id") Long id) { + projectService.deleteProject(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得项目") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('license:project:query')") + public CommonResult getProject(@RequestParam("id") Long id) { + ProjectDO project = projectService.getProject(id); + return success(BeanUtils.toBean(project, ProjectRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得项目分页") + @PreAuthorize("@ss.hasPermission('license:project:query')") + public CommonResult> getProjectPage(@Valid ProjectPageReqVO pageReqVO) { + PageResult pageResult = projectService.getProjectPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, ProjectRespVO.class)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出项目 Excel") + @PreAuthorize("@ss.hasPermission('license:project:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportProjectExcel(@Valid ProjectPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = projectService.getProjectPage(pageReqVO).getList(); + // 导出 Excel + ExcelUtils.write(response, "项目.xls", "数据", ProjectRespVO.class, + BeanUtils.toBean(list, ProjectRespVO.class)); + } + +} \ No newline at end of file diff --git a/agt-module-license/agt-module-license-server/src/main/java/org/agt/module/license/controller/admin/project/vo/ProjectPageReqVO.java b/agt-module-license/agt-module-license-server/src/main/java/org/agt/module/license/controller/admin/project/vo/ProjectPageReqVO.java new file mode 100644 index 0000000..6cc8d90 --- /dev/null +++ b/agt-module-license/agt-module-license-server/src/main/java/org/agt/module/license/controller/admin/project/vo/ProjectPageReqVO.java @@ -0,0 +1,63 @@ +package org.agt.module.license.controller.admin.project.vo; + +import lombok.*; +import java.util.*; +import io.swagger.v3.oas.annotations.media.Schema; +import org.agt.framework.common.pojo.PageParam; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; + +import static org.agt.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - 项目分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ProjectPageReqVO extends PageParam { + + @Schema(description = "项目名称", example = "aa") + private String name; + + @Schema(description = "项目编号", example = "2000") + private String code; + + @Schema(description = "合同编号", example = "1111") + private String contractCode; + + @Schema(description = "商务状态", example = "2") + private Integer businessStatus; + + @Schema(description = "业务负责人") + private Long businessOwner; + + @Schema(description = "客户对接人") + private Long customerOwner; + + @Schema(description = "技术负责人1") + private Long technicalOwnerA; + + @Schema(description = "技术负责人2") + private Long technicalOwnerB; + + @Schema(description = "技术负责人3") + private Long technicalOwnerC; + + @Schema(description = "项目开始时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] startTime; + + @Schema(description = "项目结束时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] endTime; + + @Schema(description = "项目状态", example = "2") + private Integer status; + + @Schema(description = "环境信息") + private String envInfo; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} \ No newline at end of file diff --git a/agt-module-license/agt-module-license-server/src/main/java/org/agt/module/license/controller/admin/project/vo/ProjectRespVO.java b/agt-module-license/agt-module-license-server/src/main/java/org/agt/module/license/controller/admin/project/vo/ProjectRespVO.java new file mode 100644 index 0000000..9ece749 --- /dev/null +++ b/agt-module-license/agt-module-license-server/src/main/java/org/agt/module/license/controller/admin/project/vo/ProjectRespVO.java @@ -0,0 +1,83 @@ +package org.agt.module.license.controller.admin.project.vo; + +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import org.agt.framework.excel.core.annotations.DictFormat; +import org.agt.framework.excel.core.convert.DictConvert; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - 项目 Response VO") +@Data +@ExcelIgnoreUnannotated +public class ProjectRespVO { + + @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "25585") + @ExcelProperty("主键") + private Long id; + + @Schema(description = "项目名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "aa") + @ExcelProperty("项目名称") + private String name; + + @Schema(description = "项目编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2000") + @ExcelProperty("项目编号") + private String code; + + @Schema(description = "合同编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1111") + @ExcelProperty("合同编号") + private String contractCode; + + @Schema(description = "商务状态", example = "2") + @ExcelProperty(value = "商务状态", converter = DictConvert.class) + @DictFormat("lic_business_status") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中 + private Integer businessStatus; + + @Schema(description = "业务负责人", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("业务负责人") + private Long businessOwner; + + @Schema(description = "客户对接人", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("客户对接人") + private Long customerOwner; + + @Schema(description = "技术负责人1", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("技术负责人1") + private Long technicalOwnerA; + + @Schema(description = "技术负责人2") + @ExcelProperty("技术负责人2") + private Long technicalOwnerB; + + @Schema(description = "技术负责人3") + @ExcelProperty("技术负责人3") + private Long technicalOwnerC; + + @Schema(description = "项目开始时间") + @ExcelProperty("项目开始时间") + private LocalDateTime startTime; + + @Schema(description = "项目结束时间") + @ExcelProperty("项目结束时间") + private LocalDateTime endTime; + + @Schema(description = "项目状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + @ExcelProperty(value = "项目状态", converter = DictConvert.class) + @DictFormat("lic_project_status") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中 + private Integer status; + + @Schema(description = "环境信息") + @ExcelProperty("环境信息") + private String envInfo; + + @Schema(description = "备注", example = "随便") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} \ No newline at end of file diff --git a/agt-module-license/agt-module-license-server/src/main/java/org/agt/module/license/controller/admin/project/vo/ProjectSaveReqVO.java b/agt-module-license/agt-module-license-server/src/main/java/org/agt/module/license/controller/admin/project/vo/ProjectSaveReqVO.java new file mode 100644 index 0000000..4ccfae4 --- /dev/null +++ b/agt-module-license/agt-module-license-server/src/main/java/org/agt/module/license/controller/admin/project/vo/ProjectSaveReqVO.java @@ -0,0 +1,73 @@ +package org.agt.module.license.controller.admin.project.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import jakarta.validation.constraints.*; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - 项目新增/修改 Request VO") +@Data +public class ProjectSaveReqVO { + + @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "23058") + private Long id; + + @Schema(description = "客户ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "10982") + @NotNull(message = "客户ID不能为空") + private Long customerId; + + @Schema(description = "项目名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "aa") + @NotEmpty(message = "项目名称不能为空") + private String name; + + @Schema(description = "项目编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2000") + @NotEmpty(message = "项目编号不能为空") + private String code; + + @Schema(description = "合同编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1111") + @NotEmpty(message = "合同编号不能为空") + private String contractCode; + + @Schema(description = "商务状态", example = "2") + private Integer businessStatus; + + @Schema(description = "业务负责人", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "业务负责人不能为空") + private Long businessOwner; + + @Schema(description = "客户对接人", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "客户对接人不能为空") + private Long customerOwner; + + @Schema(description = "技术负责人1", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "技术负责人1不能为空") + private Long technicalOwnerA; + + @Schema(description = "技术负责人2") + private Long technicalOwnerB; + + @Schema(description = "技术负责人3") + private Long technicalOwnerC; + + @Schema(description = "项目开始时间") + private LocalDateTime startTime; + + @Schema(description = "项目结束时间") + private LocalDateTime endTime; + + @Schema(description = "项目状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + @NotNull(message = "项目状态不能为空") + private Integer status; + + @Schema(description = "环境信息") + private String envInfo; + + @Schema(description = "环境信息附件id", example = "18887") + private Long envFileId; + + @Schema(description = "备注", example = "随便") + private String remark; + +} \ No newline at end of file diff --git a/agt-module-license/agt-module-license-server/src/main/java/org/agt/module/license/dal/dataobject/project/ProjectDO.java b/agt-module-license/agt-module-license-server/src/main/java/org/agt/module/license/dal/dataobject/project/ProjectDO.java new file mode 100644 index 0000000..c5eb9be --- /dev/null +++ b/agt-module-license/agt-module-license-server/src/main/java/org/agt/module/license/dal/dataobject/project/ProjectDO.java @@ -0,0 +1,101 @@ +package org.agt.module.license.dal.dataobject.project; + +import lombok.*; +import java.util.*; +import java.time.LocalDateTime; +import java.time.LocalDateTime; +import java.time.LocalDateTime; +import java.time.LocalDateTime; +import com.baomidou.mybatisplus.annotation.*; +import org.agt.framework.mybatis.core.dataobject.BaseDO; + +/** + * 项目 DO + * + * @author 管理员 + */ +@TableName("lic_project") +@KeySequence("lic_project_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ProjectDO extends BaseDO { + + /** + * 主键 + */ + @TableId + private Long id; + /** + * 客户ID + */ + private Long customerId; + /** + * 项目名称 + */ + private String name; + /** + * 项目编号 + */ + private String code; + /** + * 合同编号 + */ + private String contractCode; + /** + * 商务状态 + * + * 枚举 {@link TODO lic_business_type 对应的类} + */ + private Integer businessStatus; + /** + * 业务负责人 + */ + private Long businessOwner; + /** + * 客户对接人 + */ + private Long customerOwner; + /** + * 技术负责人1 + */ + private Long technicalOwnerA; + /** + * 技术负责人2 + */ + private Long technicalOwnerB; + /** + * 技术负责人3 + */ + private Long technicalOwnerC; + /** + * 项目开始时间 + */ + private LocalDateTime startTime; + /** + * 项目结束时间 + */ + private LocalDateTime endTime; + /** + * 项目状态 + * + * 枚举 {@link TODO lic_project_status 对应的类} + */ + private Integer status; + /** + * 环境信息 + */ + private String envInfo; + /** + * 环境信息附件id + */ + private Long envFileId; + /** + * 备注 + */ + private String remark; + +} \ No newline at end of file diff --git a/agt-module-license/agt-module-license-server/src/main/java/org/agt/module/license/dal/mysql/project/ProjectMapper.java b/agt-module-license/agt-module-license-server/src/main/java/org/agt/module/license/dal/mysql/project/ProjectMapper.java new file mode 100644 index 0000000..9f4f1d7 --- /dev/null +++ b/agt-module-license/agt-module-license-server/src/main/java/org/agt/module/license/dal/mysql/project/ProjectMapper.java @@ -0,0 +1,39 @@ +package org.agt.module.license.dal.mysql.project; + +import java.util.*; + +import org.agt.framework.common.pojo.PageResult; +import org.agt.framework.mybatis.core.query.LambdaQueryWrapperX; +import org.agt.framework.mybatis.core.mapper.BaseMapperX; +import org.agt.module.license.dal.dataobject.project.ProjectDO; +import org.apache.ibatis.annotations.Mapper; +import org.agt.module.license.controller.admin.project.vo.*; + +/** + * 项目 Mapper + * + * @author 管理员 + */ +@Mapper +public interface ProjectMapper extends BaseMapperX { + + default PageResult selectPage(ProjectPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(ProjectDO::getName, reqVO.getName()) + .likeIfPresent(ProjectDO::getCode, reqVO.getCode()) + .likeIfPresent(ProjectDO::getContractCode, reqVO.getContractCode()) + .eqIfPresent(ProjectDO::getBusinessStatus, reqVO.getBusinessStatus()) + .eqIfPresent(ProjectDO::getBusinessOwner, reqVO.getBusinessOwner()) + .eqIfPresent(ProjectDO::getCustomerOwner, reqVO.getCustomerOwner()) + .eqIfPresent(ProjectDO::getTechnicalOwnerA, reqVO.getTechnicalOwnerA()) + .eqIfPresent(ProjectDO::getTechnicalOwnerB, reqVO.getTechnicalOwnerB()) + .eqIfPresent(ProjectDO::getTechnicalOwnerC, reqVO.getTechnicalOwnerC()) + .betweenIfPresent(ProjectDO::getStartTime, reqVO.getStartTime()) + .betweenIfPresent(ProjectDO::getEndTime, reqVO.getEndTime()) + .eqIfPresent(ProjectDO::getStatus, reqVO.getStatus()) + .likeIfPresent(ProjectDO::getEnvInfo, reqVO.getEnvInfo()) + .betweenIfPresent(ProjectDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(ProjectDO::getId)); + } + +} \ No newline at end of file diff --git a/agt-module-license/agt-module-license-server/src/main/java/org/agt/module/license/service/project/ProjectService.java b/agt-module-license/agt-module-license-server/src/main/java/org/agt/module/license/service/project/ProjectService.java new file mode 100644 index 0000000..79aff7b --- /dev/null +++ b/agt-module-license/agt-module-license-server/src/main/java/org/agt/module/license/service/project/ProjectService.java @@ -0,0 +1,55 @@ +package org.agt.module.license.service.project; + +import java.util.*; +import jakarta.validation.*; +import org.agt.module.license.controller.admin.project.vo.*; +import org.agt.module.license.dal.dataobject.project.ProjectDO; +import org.agt.framework.common.pojo.PageResult; +import org.agt.framework.common.pojo.PageParam; + +/** + * 项目 Service 接口 + * + * @author 管理员 + */ +public interface ProjectService { + + /** + * 创建项目 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createProject(@Valid ProjectSaveReqVO createReqVO); + + /** + * 更新项目 + * + * @param updateReqVO 更新信息 + */ + void updateProject(@Valid ProjectSaveReqVO updateReqVO); + + /** + * 删除项目 + * + * @param id 编号 + */ + void deleteProject(Long id); + + /** + * 获得项目 + * + * @param id 编号 + * @return 项目 + */ + ProjectDO getProject(Long id); + + /** + * 获得项目分页 + * + * @param pageReqVO 分页查询 + * @return 项目分页 + */ + PageResult getProjectPage(ProjectPageReqVO pageReqVO); + +} \ No newline at end of file diff --git a/agt-module-license/agt-module-license-server/src/main/java/org/agt/module/license/service/project/ProjectServiceImpl.java b/agt-module-license/agt-module-license-server/src/main/java/org/agt/module/license/service/project/ProjectServiceImpl.java new file mode 100644 index 0000000..c4ed922 --- /dev/null +++ b/agt-module-license/agt-module-license-server/src/main/java/org/agt/module/license/service/project/ProjectServiceImpl.java @@ -0,0 +1,74 @@ +package org.agt.module.license.service.project; + +import org.springframework.stereotype.Service; +import jakarta.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.transaction.annotation.Transactional; + +import java.util.*; +import org.agt.module.license.controller.admin.project.vo.*; +import org.agt.module.license.dal.dataobject.project.ProjectDO; +import org.agt.framework.common.pojo.PageResult; +import org.agt.framework.common.pojo.PageParam; +import org.agt.framework.common.util.object.BeanUtils; + +import org.agt.module.license.dal.mysql.project.ProjectMapper; + +import static org.agt.framework.common.exception.util.ServiceExceptionUtil.exception; +import static org.agt.module.license.enums.ErrorCodeConstants.*; + +/** + * 项目 Service 实现类 + * + * @author 管理员 + */ +@Service +@Validated +public class ProjectServiceImpl implements ProjectService { + + @Resource + private ProjectMapper projectMapper; + + @Override + public Long createProject(ProjectSaveReqVO createReqVO) { + // 插入 + ProjectDO project = BeanUtils.toBean(createReqVO, ProjectDO.class); + projectMapper.insert(project); + // 返回 + return project.getId(); + } + + @Override + public void updateProject(ProjectSaveReqVO updateReqVO) { + // 校验存在 + validateProjectExists(updateReqVO.getId()); + // 更新 + ProjectDO updateObj = BeanUtils.toBean(updateReqVO, ProjectDO.class); + projectMapper.updateById(updateObj); + } + + @Override + public void deleteProject(Long id) { + // 校验存在 + validateProjectExists(id); + // 删除 + projectMapper.deleteById(id); + } + + private void validateProjectExists(Long id) { + if (projectMapper.selectById(id) == null) { + throw exception(PROJECT_NOT_EXISTS); + } + } + + @Override + public ProjectDO getProject(Long id) { + return projectMapper.selectById(id); + } + + @Override + public PageResult getProjectPage(ProjectPageReqVO pageReqVO) { + return projectMapper.selectPage(pageReqVO); + } + +} \ No newline at end of file diff --git a/agt-module-license/agt-module-license-server/src/main/resources/mapper/project/ProjectMapper.xml b/agt-module-license/agt-module-license-server/src/main/resources/mapper/project/ProjectMapper.xml new file mode 100644 index 0000000..a1a8ddd --- /dev/null +++ b/agt-module-license/agt-module-license-server/src/main/resources/mapper/project/ProjectMapper.xml @@ -0,0 +1,12 @@ + + + + + + + \ No newline at end of file