feat: 项目进展报表

This commit is contained in:
caiyuchao
2025-09-09 17:56:11 +08:00
parent 5b5daef2e0
commit 19dec923e4
7 changed files with 366 additions and 0 deletions

View File

@@ -0,0 +1,41 @@
package org.agt.module.license.controller.admin.report;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.agt.framework.common.pojo.CommonResult;
import org.agt.framework.common.pojo.PageResult;
import org.agt.module.license.controller.admin.report.vo.ReportProgressProjectReqVO;
import org.agt.module.license.controller.admin.report.vo.ReportProgressProjectRespVO;
import org.agt.module.license.service.report.ReportService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import static org.agt.framework.common.pojo.CommonResult.success;
@Tag(name = "管理后台 - 报表")
@RestController
@RequestMapping("/license/report")
@Validated
public class ReportController {
@Resource
private ReportService reportService;
@GetMapping("/progress/project-page")
@Operation(summary = "获得项目维度的评论列表")
public CommonResult<PageResult<ReportProgressProjectRespVO>> getCommentByProject(@Valid ReportProgressProjectReqVO query) {
PageResult<ReportProgressProjectRespVO> pageResult = reportService.getCommentByProject(query);
return success(pageResult);
}
@GetMapping("/progress/staff-page")
@Operation(summary = "获得人员维度的评论列表")
public CommonResult<PageResult<ReportProgressProjectRespVO>> getCommentByStaff(@Valid ReportProgressProjectReqVO query) {
PageResult<ReportProgressProjectRespVO> pageResult = reportService.getCommentByStaff(query);
return success(pageResult);
}
}

View File

@@ -0,0 +1,87 @@
package org.agt.module.license.controller.admin.report.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.agt.framework.common.pojo.PageParam;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import static org.agt.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY;
import static org.agt.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 报表 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ReportProgressProjectReqVO extends PageParam {
@Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "4294")
private Long id;
@Schema(description = "项目ID", example = "18334")
private Long projectId;
@Schema(description = "项目名称", example = "18334")
private String projectName;
@Schema(description = "项目状态", example = "18334")
private Integer status;
@Schema(description = "serialNo", example = "随便")
private String serialNo;
@Schema(description = "业务负责人")
private String businessOwner;
@Schema(description = "技术负责人1")
private String technicalOwnerA;
@Schema(description = "客户名称")
private String customerName;
@Schema(description = "客户id")
private Long customerId;
@Schema(description = "用户ID", example = "30248")
private Long userId;
@Schema(description = "父ID", example = "20143")
private Long parentId;
@Schema(description = "内容")
private String content;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
@Schema(description = "更新时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] updateTime;
@Schema(description = "更新时间-开始")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY)
private LocalDate updateTimeStart;
@Schema(description = "更新时间-结束")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY)
private LocalDate updateTimeEnd;
@Schema(description = "评论用户")
private String author;
@Schema(description = "评论用户ID")
private Long authorId;
@Schema(description = "评论用户头像")
private String avatar;
@Schema(description = "回复用户ID", example = "30248")
private Long replyUserId;
@Schema(description = "回复用户")
private String replyUser;
}

View File

@@ -0,0 +1,86 @@
package org.agt.module.license.controller.admin.report.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 java.time.LocalDateTime;
import java.util.List;
@Schema(description = "管理后台 - 报表 Response VO")
@Data
@ExcelIgnoreUnannotated
public class ReportProgressProjectRespVO {
@Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "4294")
@ExcelProperty("主键")
private Long id;
@Schema(description = "项目ID", example = "18334")
@ExcelProperty("项目ID")
private Long projectId;
@Schema(description = "项目名称", example = "18334")
private String projectName;
@Schema(description = "项目状态", example = "18334")
private Integer status;
@Schema(description = "serialNo", example = "随便")
private String serialNo;
@Schema(description = "业务负责人")
private String businessOwnerName;
@Schema(description = "技术负责人1")
private String technicalOwnerAName;
@Schema(description = "技术负责人2")
private String technicalOwnerBName;
@Schema(description = "客户名称")
private String customerName;
@Schema(description = "用户ID", example = "30248")
@ExcelProperty("用户ID")
private Long userId;
@Schema(description = "父ID", example = "20143")
@ExcelProperty("父ID")
private Long parentId;
@Schema(description = "内容")
@ExcelProperty("内容")
private String content;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("创建时间")
private LocalDateTime createTime;
@Schema(description = "项目开始时间", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("项目开始时间")
private LocalDateTime startTime;
@Schema(description = "更新时间", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("更新时间")
private LocalDateTime updateTime;
@Schema(description = "评论用户")
private String author;
@Schema(description = "评论用户头像")
private String avatar;
@Schema(description = "回复用户ID", example = "30248")
private Long replyUserId;
@Schema(description = "回复用户")
private String replyUser;
@Schema(description = "深度")
private Integer depth;
@Schema(description = "子列表")
private List<ReportProgressProjectRespVO> children;
}

View File

@@ -0,0 +1,20 @@
package org.agt.module.license.dal.mysql.report;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.agt.module.license.controller.admin.report.vo.ReportProgressProjectReqVO;
import org.agt.module.license.controller.admin.report.vo.ReportProgressProjectRespVO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
/**
* 评论 Mapper
*
* @author 管理员
*/
@Mapper
public interface ReportMapper {
IPage<ReportProgressProjectRespVO> getCommentByProject(IPage<?> page, @Param("query") ReportProgressProjectReqVO query);
IPage<ReportProgressProjectRespVO> getCommentByStaff(IPage<?> page, @Param("query") ReportProgressProjectReqVO query);
}

View File

@@ -0,0 +1,17 @@
package org.agt.module.license.service.report;
import org.agt.framework.common.pojo.PageResult;
import org.agt.module.license.controller.admin.report.vo.ReportProgressProjectReqVO;
import org.agt.module.license.controller.admin.report.vo.ReportProgressProjectRespVO;
/**
* 报表 Service 接口
*
* @author 管理员
*/
public interface ReportService {
PageResult<ReportProgressProjectRespVO> getCommentByProject(ReportProgressProjectReqVO query);
PageResult<ReportProgressProjectRespVO> getCommentByStaff(ReportProgressProjectReqVO query);
}

View File

@@ -0,0 +1,39 @@
package org.agt.module.license.service.report;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import jakarta.annotation.Resource;
import org.agt.framework.common.pojo.PageResult;
import org.agt.module.license.controller.admin.report.vo.ReportProgressProjectReqVO;
import org.agt.module.license.controller.admin.report.vo.ReportProgressProjectRespVO;
import org.agt.module.license.dal.mysql.report.ReportMapper;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
/**
* 报表 Service 实现类
*
* @author 管理员
*/
@Service
@Validated
public class ReportServiceImpl implements ReportService {
@Resource
private ReportMapper reportMapper;
@Override
public PageResult<ReportProgressProjectRespVO> getCommentByProject(ReportProgressProjectReqVO pageReqVO) {
IPage<ReportProgressProjectRespVO> page = reportMapper.getCommentByProject(new Page<>(pageReqVO.getPageNo(), pageReqVO.getPageSize()), pageReqVO);
return new PageResult<>(page.getRecords(), page.getTotal());
}
@Override
public PageResult<ReportProgressProjectRespVO> getCommentByStaff(ReportProgressProjectReqVO pageReqVO) {
IPage<ReportProgressProjectRespVO> page = reportMapper.getCommentByStaff(new Page<>(pageReqVO.getPageNo(), pageReqVO.getPageSize()), pageReqVO);
return new PageResult<>(page.getRecords(), page.getTotal());
}
}

View File

@@ -0,0 +1,76 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.agt.module.license.dal.mysql.report.ReportMapper">
<select id="getCommentByProject" resultType="org.agt.module.license.controller.admin.report.vo.ReportProgressProjectRespVO">
<include refid="comment"></include>
ORDER BY
p.update_time DESC,
c.update_time DESC
</select>
<select id="getCommentByStaff" resultType="org.agt.module.license.controller.admin.report.vo.ReportProgressProjectRespVO">
<include refid="comment"></include>
ORDER BY
mt.max_update_time DESC,
c.update_time DESC
</select>
<sql id="comment">
SELECT
p.`name` project_name,
p.`status` status,
p.start_time,
cu.`name` customer_name,
l.serial_no,
u.nickname author,
c.*,
u.avatar,
pc.user_id reply_user_id,
pu.nickname reply_user,
bo.nickname business_owner_name,
toa.nickname technical_owner_a_name,
tob.nickname technical_owner_b_name
FROM
crm_project p
LEFT JOIN crm_customer cu ON p.customer_id = cu.id
AND cu.deleted = 0
LEFT JOIN ( SELECT project_id, GROUP_CONCAT( serial_no ) serial_no FROM crm_license_server WHERE deleted = 0 GROUP BY project_id ) l ON l.project_id = p.id
LEFT JOIN crm_comment c ON p.id = c.project_id
AND c.deleted = 0
LEFT JOIN system_users u ON c.user_id = u.id
AND u.deleted = 0
LEFT JOIN ( SELECT user_id, max( update_time ) max_update_time FROM crm_comment WHERE deleted = 0 GROUP BY user_id ) mt ON u.id = mt.user_id
LEFT JOIN crm_comment pc ON c.parent_id = pc.id
AND pc.deleted = 0
LEFT JOIN system_users pu ON pc.user_id = pu.id
AND pu.deleted = 0
LEFT JOIN system_users bo ON p.business_owner = bo.id
AND bo.deleted = 0
LEFT JOIN system_users toa ON p.technical_owner_a = toa.id
AND toa.deleted = 0
LEFT JOIN system_users tob ON p.technical_owner_b = tob.id
AND tob.deleted = 0
WHERE
p.deleted = 0
AND c.id IS NOT NULL
<if test="query.customerId != null">
AND p.customer_id = #{query.customerId}
</if>
<if test="query.projectId != null">
AND p.id = #{query.projectId}
</if>
<if test="query.serialNo != null and query.serialNo != ''">
AND l.serial_no LIKE CONCAT('%',#{query.serialNo},'%')
</if>
<if test="query.updateTime != null and query.updateTime.length > 1">
AND c.update_time BETWEEN #{query.updateTime[0]} AND #{query.updateTime[1]}
</if>
<if test="query.updateTimeStart != null and query.updateTimeEnd != null">
AND DATE_FORMAT(c.update_time, '%Y-%m-%d') BETWEEN DATE_FORMAT(#{query.updateTimeStart}, '%Y-%m-%d') AND DATE_FORMAT(#{query.updateTimeEnd}, '%Y-%m-%d')
</if>
<if test="query.authorId != null">
AND u.id = #{query.authorId}
</if>
</sql>
</mapper>