feat(项目看板): 新增项目综合看板功能
新增项目综合看板功能,聚合展示项目、任务、进度主表和步骤数据
- 新增后端聚合接口 GET /oa/project/dashboard/{projectId}
- 新增前端看板页面,包含项目列表、任务表格和进度导图
- 优化思维导图组件,支持看板模式下的紧凑展示
- 新增进度明细表格视图和状态图例
- 实现任务与进度步骤的关联展示
- 添加项目模糊搜索功能
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
package com.ruoyi.oa.controller;
|
||||
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.R;
|
||||
import com.ruoyi.oa.domain.bo.OaProjectScheduleBo;
|
||||
import com.ruoyi.oa.domain.bo.OaProjectScheduleStepBo;
|
||||
import com.ruoyi.oa.domain.vo.OaProjectScheduleStepVo;
|
||||
import com.ruoyi.oa.domain.vo.OaProjectScheduleVo;
|
||||
import com.ruoyi.oa.domain.vo.OaScheduleListVo;
|
||||
import com.ruoyi.oa.service.IOaProjectScheduleService;
|
||||
import com.ruoyi.oa.service.IOaProjectScheduleStepService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
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.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 项目进度(主表 + 子表聚合)
|
||||
*
|
||||
* 该控制器用于满足综合看板接口规范:
|
||||
* - GET /oa/schedule/list?projectId=xx
|
||||
*
|
||||
* 复用现有服务:
|
||||
* - /oa/projectSchedule(主表)
|
||||
* - /oa/projectScheduleStep(子表)
|
||||
*/
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/oa/schedule")
|
||||
public class OaScheduleController extends BaseController {
|
||||
|
||||
private final IOaProjectScheduleService projectScheduleService;
|
||||
private final IOaProjectScheduleStepService projectScheduleStepService;
|
||||
|
||||
/**
|
||||
* 获取进度主表 + 子表数据
|
||||
*
|
||||
* @param projectId 项目ID
|
||||
*/
|
||||
@GetMapping("/list")
|
||||
public R<List<OaScheduleListVo>> list(@RequestParam("projectId") Long projectId) {
|
||||
OaProjectScheduleBo scheduleBo = new OaProjectScheduleBo();
|
||||
scheduleBo.setProjectId(projectId);
|
||||
List<OaProjectScheduleVo> schedules = projectScheduleService.queryList(scheduleBo);
|
||||
|
||||
List<OaScheduleListVo> result = new ArrayList<>();
|
||||
for (OaProjectScheduleVo schedule : schedules) {
|
||||
List<OaProjectScheduleStepVo> steps = projectScheduleStepService.selectProjectScheduleStepList(schedule.getScheduleId());
|
||||
|
||||
OaScheduleListVo vo = new OaScheduleListVo();
|
||||
vo.setSchedule(schedule);
|
||||
vo.setStepList(steps);
|
||||
result.add(vo);
|
||||
}
|
||||
return R.ok(result);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,6 +87,17 @@ public class SysOaProjectController extends BaseController {
|
||||
return R.ok(iSysOaProjectService.getMaxCode(prefix));
|
||||
}
|
||||
|
||||
/**
|
||||
* 项目综合看板聚合数据(项目 + 任务 + 进度主表 + 步骤)
|
||||
* 必须声明在 /{projectId} 之前,避免部分环境下通配路径优先匹配导致 404。
|
||||
* 菜单权限请在 sys_menu 中配置后使用全局路由守卫或接口级注解单独加回。
|
||||
*/
|
||||
@GetMapping("/dashboard/{projectId}")
|
||||
public R<OaProjectDashboardVo> dashboard(@NotNull(message = "主键不能为空") @PathVariable Long projectId) {
|
||||
OaProjectDashboardVo data = iSysOaProjectService.getProjectDashboard(projectId);
|
||||
return data == null ? R.fail("项目不存在") : R.ok(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取项目管理详细信息
|
||||
*
|
||||
|
||||
@@ -201,6 +201,12 @@ public class SysOaProjectBo extends BaseEntity {
|
||||
private Long customerId;
|
||||
//客户名称
|
||||
private String customerName;
|
||||
|
||||
/**
|
||||
* 综合模糊查询(名称 / 编号 / 代号 任一匹配),与 projectName、projectNum、projectCode 互斥:有值时优先使用本字段
|
||||
*/
|
||||
private String keyword;
|
||||
|
||||
//是否置顶
|
||||
private Integer isTop;
|
||||
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.ruoyi.oa.domain.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 项目综合看板聚合数据
|
||||
*/
|
||||
@Data
|
||||
public class OaProjectDashboardVo implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private SysOaProjectVo project;
|
||||
|
||||
private List<SysOaTaskVo> tasks;
|
||||
|
||||
private List<OaProjectScheduleVo> schedules;
|
||||
|
||||
private List<OaProjectScheduleStepVo> steps;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.ruoyi.oa.domain.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 项目进度列表(主表 + 子表)
|
||||
*
|
||||
* 对应表:
|
||||
* - oa_project_schedule(主表)
|
||||
* - oa_project_schedule_step(子表)
|
||||
*
|
||||
* 该 VO 用于接口:GET /oa/schedule/list
|
||||
*/
|
||||
@Data
|
||||
public class OaScheduleListVo implements Serializable {
|
||||
|
||||
/** 进度主表 */
|
||||
private OaProjectScheduleVo schedule;
|
||||
|
||||
/** 进度子表步骤 */
|
||||
private List<OaProjectScheduleStepVo> stepList;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package com.ruoyi.oa.domain.vo;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
@@ -218,11 +216,28 @@ public class SysOaTaskVo {
|
||||
//部门名称
|
||||
private String deptName;
|
||||
|
||||
//关联项目进度id
|
||||
/** 关联进度子表主键 oa_project_schedule_step.track_id */
|
||||
private Long trackId;
|
||||
|
||||
//联查的节点信息
|
||||
private String tabNode;
|
||||
private String firstLevelNode;
|
||||
private String secondLevelNode;
|
||||
|
||||
/** 进度步骤名称 oa_project_schedule_step.step_name(综合看板联表) */
|
||||
private String scheduleStepName;
|
||||
|
||||
/** 进度步骤状态 0未开始 1进行中 2完成 3暂停 */
|
||||
private Long scheduleStatus;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd")
|
||||
private Date schedulePlanStart;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd")
|
||||
private Date schedulePlanEnd;
|
||||
|
||||
/** 进度负责人 oa_project_schedule_step.header */
|
||||
private String scheduleHeader;
|
||||
}
|
||||
|
||||
@@ -31,6 +31,11 @@ public interface OaProjectScheduleStepMapper extends BaseMapperPlus<OaProjectSch
|
||||
|
||||
void saveBatch(List<OaProjectScheduleStep> entities);
|
||||
|
||||
/**
|
||||
* 按 schedule_id 查询步骤列表(综合看板使用)
|
||||
*/
|
||||
List<OaProjectScheduleStepVo> selectProjectScheduleStepList(@Param("scheduleId") Long scheduleId);
|
||||
|
||||
/**
|
||||
* 根据 schedule_id 批量删除步骤记录
|
||||
* @param scheduleIds 主表的 schedule_id 集合
|
||||
|
||||
@@ -46,6 +46,11 @@ public interface SysOaTaskMapper extends BaseMapperPlus<SysOaTaskMapper, SysOaTa
|
||||
|
||||
List<SysOaTaskVo> listDocumentProject(Long projectId);
|
||||
|
||||
/**
|
||||
* 综合看板:某项目下任务(一行一条任务)
|
||||
*/
|
||||
List<SysOaTaskVo> selectDashboardTasksByProjectId(@Param("projectId") Long projectId);
|
||||
|
||||
/**
|
||||
* 新增:自定义查询任务列表(Plus版)
|
||||
*/
|
||||
|
||||
@@ -38,6 +38,11 @@ public interface IOaProjectScheduleStepService{
|
||||
*/
|
||||
List<OaProjectScheduleStepVo> queryList(OaProjectScheduleStepBo bo);
|
||||
|
||||
/**
|
||||
* 按 scheduleId 查询进度步骤列表(综合看板聚合接口使用)
|
||||
*/
|
||||
List<OaProjectScheduleStepVo> selectProjectScheduleStepList(Long scheduleId);
|
||||
|
||||
/**
|
||||
* 新增项目进度步骤跟踪
|
||||
*/
|
||||
|
||||
@@ -103,4 +103,9 @@ public interface ISysOaProjectService {
|
||||
Boolean postponeProject(SysOaProject bo);
|
||||
|
||||
SysOaProjectVo getMaxCode(String prefix);
|
||||
|
||||
/**
|
||||
* 综合看板:项目详情 + 任务 + 进度主表 + 进度步骤(一次返回)
|
||||
*/
|
||||
OaProjectDashboardVo getProjectDashboard(Long projectId);
|
||||
}
|
||||
|
||||
@@ -109,6 +109,11 @@ public interface ISysOaTaskService {
|
||||
* @return
|
||||
*/
|
||||
List<SysOaTaskVo> listDocumentProject(Long projectId);
|
||||
|
||||
/**
|
||||
* 综合看板任务列表(完整字段,无 task_item 重复行)
|
||||
*/
|
||||
List<SysOaTaskVo> listDashboardTasks(Long projectId);
|
||||
/**
|
||||
* 新增:自定义查询任务列表(Plus版)
|
||||
*/
|
||||
|
||||
@@ -68,7 +68,8 @@ public class OaProjectScheduleServiceImpl implements IOaProjectScheduleService {
|
||||
*/
|
||||
@Override
|
||||
public TableDataInfo<OaProjectScheduleVo> queryPageList(OaProjectScheduleBo bo, PageQuery pageQuery) {
|
||||
QueryWrapper<OaProjectSchedule> lqw = buildQueryWrapper(bo);
|
||||
// 分页列表走自定义 Join SQL(XML 中存在 ops/op 别名)
|
||||
QueryWrapper<OaProjectSchedule> lqw = buildQueryWrapperJoin(bo);
|
||||
Page<OaProjectScheduleVo> result = baseMapper.selectVoPagePlus(pageQuery.build(), lqw);
|
||||
return TableDataInfo.build(result);
|
||||
}
|
||||
@@ -78,11 +79,17 @@ public class OaProjectScheduleServiceImpl implements IOaProjectScheduleService {
|
||||
*/
|
||||
@Override
|
||||
public List<OaProjectScheduleVo> queryList(OaProjectScheduleBo bo) {
|
||||
QueryWrapper<OaProjectSchedule> lqw = buildQueryWrapper(bo);
|
||||
// 非分页列表走 BaseMapper 默认 SQL(无 ops/op 别名),避免出现 ops.del_flag 这类不存在的列引用
|
||||
QueryWrapper<OaProjectSchedule> lqw = buildQueryWrapperBase(bo);
|
||||
return baseMapper.selectVoList(lqw);
|
||||
}
|
||||
|
||||
private QueryWrapper<OaProjectSchedule> buildQueryWrapper(OaProjectScheduleBo bo) {
|
||||
/**
|
||||
* Join 场景查询条件(对应 XML: OaProjectScheduleMapper.selectVoPagePlus)
|
||||
* - 主表别名:ops (oa_project_schedule)
|
||||
* - 项目表别名:op (sys_oa_project)
|
||||
*/
|
||||
private QueryWrapper<OaProjectSchedule> buildQueryWrapperJoin(OaProjectScheduleBo bo) {
|
||||
Map<String, Object> params = bo.getParams();
|
||||
QueryWrapper<OaProjectSchedule> lqw = Wrappers.query();
|
||||
lqw.eq("ops.del_flag", 0);
|
||||
@@ -112,6 +119,27 @@ public class OaProjectScheduleServiceImpl implements IOaProjectScheduleService {
|
||||
return lqw;
|
||||
}
|
||||
|
||||
/**
|
||||
* Base 表场景查询条件(对应 BaseMapper 默认 SQL:FROM oa_project_schedule)
|
||||
* 仅使用 oa_project_schedule 表字段,严格对齐表结构:
|
||||
* - oa_project_schedule(project_id、schedule_id、...、del_flag)
|
||||
*/
|
||||
private QueryWrapper<OaProjectSchedule> buildQueryWrapperBase(OaProjectScheduleBo bo) {
|
||||
QueryWrapper<OaProjectSchedule> lqw = Wrappers.query();
|
||||
// TableLogic 字段,默认查询只取未删除
|
||||
lqw.eq("del_flag", 0);
|
||||
lqw.eq(bo.getProjectId() != null, "project_id", bo.getProjectId());
|
||||
lqw.eq(bo.getTemplateId() != null, "template_id", bo.getTemplateId());
|
||||
lqw.eq(bo.getCurrentStep() != null, "current_step", bo.getCurrentStep());
|
||||
lqw.eq(bo.getStatus() != null, "status", bo.getStatus());
|
||||
lqw.eq(bo.getSteward() != null, "steward", bo.getSteward());
|
||||
// 使用 startTime / endTime 进行范围筛选
|
||||
lqw.between(bo.getStartTime() != null && bo.getEndTime() != null, "start_time", bo.getStartTime(), bo.getEndTime());
|
||||
lqw.ge(bo.getStartTime() != null && bo.getEndTime() == null, "start_time", bo.getStartTime());
|
||||
lqw.le(bo.getStartTime() == null && bo.getEndTime() != null, "end_time", bo.getEndTime());
|
||||
return lqw;
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增项目进度
|
||||
*/
|
||||
|
||||
@@ -95,13 +95,13 @@ public class OaProjectScheduleStepServiceImpl implements IOaProjectScheduleStepS
|
||||
*/
|
||||
@Override
|
||||
public TableDataInfo<OaProjectScheduleStepVo> queryPageList(OaProjectScheduleStepBo bo, PageQuery pageQuery) {
|
||||
QueryWrapper<OaProjectScheduleStep> lqw = buildQueryWrapper(bo);
|
||||
QueryWrapper<OaProjectScheduleStep> lqw = buildQueryWrapper(bo, true);
|
||||
Page<OaProjectScheduleStepVo> result = baseMapper.selectVoPagePlus(pageQuery.build(), lqw,LoginHelper.getUserId());
|
||||
return TableDataInfo.build(result);
|
||||
}
|
||||
@Override
|
||||
public TableDataInfo<OaProjectScheduleStepVo> queryPageListPage(OaProjectScheduleStepBo bo, PageQuery pageQuery) {
|
||||
QueryWrapper<OaProjectScheduleStep> lqw = buildQueryWrapper(bo);
|
||||
QueryWrapper<OaProjectScheduleStep> lqw = buildQueryWrapper(bo, true);
|
||||
Page<OaProjectScheduleStepVo> result = baseMapper.selectVoPageNew(pageQuery.build(), lqw);
|
||||
return TableDataInfo.build(result);
|
||||
}
|
||||
@@ -113,22 +113,13 @@ public class OaProjectScheduleStepServiceImpl implements IOaProjectScheduleStepS
|
||||
return TableDataInfo.build(result);
|
||||
}
|
||||
private QueryWrapper<OaProjectScheduleStep> buildQueryMyWrapper(OaProjectScheduleStepBo bo) {
|
||||
Map<String, Object> params = bo.getParams();
|
||||
QueryWrapper<OaProjectScheduleStep> lqw = Wrappers.query();
|
||||
lqw.eq(bo.getScheduleId() != null, "opss.schedule_id", bo.getScheduleId());
|
||||
lqw.eq("opss.del_flag", 0);
|
||||
lqw.eq(bo.getStepOrder() != null, "opss.step_order", bo.getStepOrder());
|
||||
lqw.like(StringUtils.isNotBlank(bo.getStepName()), "opss.step_name", bo.getStepName());
|
||||
lqw.eq(bo.getStatus() != null, "opss.status", bo.getStatus());
|
||||
appendCommonStepFilters(lqw, bo, "opss");
|
||||
// 默认将负责人设置为当前用户
|
||||
String currentUser = LoginHelper.getNickName();
|
||||
lqw.eq(StringUtils.isNotBlank(currentUser), "opss.node_header", currentUser);
|
||||
lqw.eq(bo.getSupplierId() != null, "opss.supplier_id", bo.getSupplierId());
|
||||
//根据开始时间和结束时间作为范围判断planEnd
|
||||
lqw.ge(bo.getStartTime() != null, "opss.plan_end", bo.getStartTime());
|
||||
lqw.le(bo.getEndTime() != null, "opss.plan_end", bo.getEndTime());
|
||||
lqw.eq(StringUtils.isNotBlank(currentUser), stepCol("opss", "node_header"), currentUser);
|
||||
// 按时间倒序排列,已完成的排在最后
|
||||
lqw.orderByDesc("opss.plan_end");
|
||||
lqw.orderByDesc(stepCol("opss", "plan_end"));
|
||||
lqw.orderByAsc("opss.status = 2"); // 状态为2表示已完成,将其排在最后
|
||||
return lqw;
|
||||
}
|
||||
@@ -137,26 +128,41 @@ public class OaProjectScheduleStepServiceImpl implements IOaProjectScheduleStepS
|
||||
*/
|
||||
@Override
|
||||
public List<OaProjectScheduleStepVo> queryList(OaProjectScheduleStepBo bo) {
|
||||
QueryWrapper<OaProjectScheduleStep> lqw = buildQueryWrapper(bo);
|
||||
QueryWrapper<OaProjectScheduleStep> lqw = buildQueryWrapper(bo, false);
|
||||
return baseMapper.selectVoList(lqw);
|
||||
}
|
||||
|
||||
private QueryWrapper<OaProjectScheduleStep> buildQueryWrapper(OaProjectScheduleStepBo bo) {
|
||||
Map<String, Object> params = bo.getParams();
|
||||
@Override
|
||||
public List<OaProjectScheduleStepVo> selectProjectScheduleStepList(Long scheduleId) {
|
||||
return baseMapper.selectProjectScheduleStepList(scheduleId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param forJoinSql true:XML 中带 opss/schedule 等多表别名,条件须加 opss. 前缀,避免 schedule_id 等列歧义
|
||||
*/
|
||||
private QueryWrapper<OaProjectScheduleStep> buildQueryWrapper(OaProjectScheduleStepBo bo, boolean forJoinSql) {
|
||||
QueryWrapper<OaProjectScheduleStep> lqw = Wrappers.query();
|
||||
lqw.eq(bo.getScheduleId() != null, "opss.schedule_id", bo.getScheduleId());
|
||||
lqw.eq("opss.del_flag", 0);
|
||||
lqw.eq(bo.getStepOrder() != null, "opss.step_order", bo.getStepOrder());
|
||||
lqw.like(StringUtils.isNotBlank(bo.getStepName()), "opss.step_name", bo.getStepName());
|
||||
lqw.eq(bo.getStatus() != null, "opss.status", bo.getStatus());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getNodeHeader()), "opss.node_header", bo.getNodeHeader());
|
||||
lqw.eq(bo.getSupplierId() != null, "opss.supplier_id", bo.getSupplierId());
|
||||
//根据开始时间和结束时间作为范围判断planEnd
|
||||
lqw.ge(bo.getStartTime() != null, "opss.plan_end", bo.getStartTime());
|
||||
lqw.le(bo.getEndTime() != null, "opss.plan_end", bo.getEndTime());
|
||||
String alias = forJoinSql ? "opss" : null;
|
||||
appendCommonStepFilters(lqw, bo, alias);
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getNodeHeader()), stepCol(alias, "node_header"), bo.getNodeHeader());
|
||||
return lqw;
|
||||
}
|
||||
|
||||
private static String stepCol (String tableAlias, String column) {
|
||||
return StringUtils.isBlank(tableAlias) ? column : tableAlias + "." + column;
|
||||
}
|
||||
|
||||
/** 步骤表公共筛选(与 oa_project_schedule 联表时须使用别名 opss) */
|
||||
private void appendCommonStepFilters (QueryWrapper<OaProjectScheduleStep> lqw, OaProjectScheduleStepBo bo, String alias) {
|
||||
lqw.eq(bo.getScheduleId() != null, stepCol(alias, "schedule_id"), bo.getScheduleId());
|
||||
lqw.eq(bo.getStepOrder() != null, stepCol(alias, "step_order"), bo.getStepOrder());
|
||||
lqw.like(StringUtils.isNotBlank(bo.getStepName()), stepCol(alias, "step_name"), bo.getStepName());
|
||||
lqw.eq(bo.getStatus() != null, stepCol(alias, "status"), bo.getStatus());
|
||||
lqw.eq(bo.getSupplierId() != null, stepCol(alias, "supplier_id"), bo.getSupplierId());
|
||||
lqw.ge(bo.getStartTime() != null, stepCol(alias, "plan_end"), bo.getStartTime());
|
||||
lqw.le(bo.getEndTime() != null, stepCol(alias, "plan_end"), bo.getEndTime());
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增项目进度步骤跟踪
|
||||
*/
|
||||
|
||||
@@ -12,12 +12,16 @@ import com.ruoyi.common.core.domain.PageQuery;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.ruoyi.oa.domain.bo.OaProjectScheduleBo;
|
||||
import com.ruoyi.oa.domain.bo.SysOaWarehouseDetailBo;
|
||||
import com.ruoyi.oa.domain.dto.ProjectActivityDTO;
|
||||
import com.ruoyi.oa.domain.dto.ProjectDataDTO;
|
||||
import com.ruoyi.oa.domain.vo.*;
|
||||
import com.ruoyi.oa.service.CodeGeneratorService;
|
||||
import com.ruoyi.oa.service.IExchangeRateService;
|
||||
import com.ruoyi.oa.service.IOaProjectScheduleService;
|
||||
import com.ruoyi.oa.service.IOaProjectScheduleStepService;
|
||||
import com.ruoyi.oa.service.ISysOaTaskService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -43,6 +47,12 @@ public class SysOaProjectServiceImpl implements ISysOaProjectService {
|
||||
|
||||
private final SysOaProjectMapper baseMapper;
|
||||
|
||||
private final ISysOaTaskService sysOaTaskService;
|
||||
|
||||
private final IOaProjectScheduleService oaProjectScheduleService;
|
||||
|
||||
private final IOaProjectScheduleStepService oaProjectScheduleStepService;
|
||||
|
||||
@Autowired
|
||||
private CodeGeneratorService codeGeneratorService;
|
||||
@Autowired
|
||||
@@ -187,9 +197,16 @@ public class SysOaProjectServiceImpl implements ISysOaProjectService {
|
||||
private QueryWrapper<SysOaProject> buildAliasPQueryWrapper(SysOaProjectBo bo) {
|
||||
Map<String, Object> params = bo.getParams();
|
||||
QueryWrapper<SysOaProject> qw = Wrappers.query();
|
||||
qw.like(StringUtils.isNotBlank(bo.getProjectName()), "p.project_name", bo.getProjectName());
|
||||
qw.like(StringUtils.isNotBlank(bo.getProjectNum()), "p.project_num", bo.getProjectNum());
|
||||
qw.like(StringUtils.isNotBlank(bo.getProjectCode()), "p.project_code", bo.getProjectCode());
|
||||
if (StringUtils.isNotBlank(bo.getKeyword())) {
|
||||
String kw = bo.getKeyword().trim();
|
||||
qw.and(w -> w.like("p.project_name", kw)
|
||||
.or().like("p.project_num", kw)
|
||||
.or().like("p.project_code", kw));
|
||||
} else {
|
||||
qw.like(StringUtils.isNotBlank(bo.getProjectName()), "p.project_name", bo.getProjectName());
|
||||
qw.like(StringUtils.isNotBlank(bo.getProjectNum()), "p.project_num", bo.getProjectNum());
|
||||
qw.like(StringUtils.isNotBlank(bo.getProjectCode()), "p.project_code", bo.getProjectCode());
|
||||
}
|
||||
qw.eq(bo.getProductStatus() != null, "p.product_status", bo.getProductStatus());
|
||||
qw.eq(bo.getTradeType() != null, "p.trade_type", bo.getTradeType());
|
||||
if (bo.getPrePay() != null && bo.getPrePay() > 0) {
|
||||
@@ -219,9 +236,16 @@ public class SysOaProjectServiceImpl implements ISysOaProjectService {
|
||||
private LambdaQueryWrapper<SysOaProject> buildQueryWrapper(SysOaProjectBo bo) {
|
||||
Map<String, Object> params = bo.getParams();
|
||||
LambdaQueryWrapper<SysOaProject> lqw = Wrappers.lambdaQuery();
|
||||
lqw.like(StringUtils.isNotBlank(bo.getProjectName()), SysOaProject::getProjectName, bo.getProjectName());
|
||||
lqw.like(StringUtils.isNotBlank(bo.getProjectNum()), SysOaProject::getProjectNum, bo.getProjectNum());
|
||||
lqw.like(StringUtils.isNotBlank(bo.getProjectCode()), SysOaProject::getProjectCode, bo.getProjectCode());
|
||||
if (StringUtils.isNotBlank(bo.getKeyword())) {
|
||||
String kw = bo.getKeyword().trim();
|
||||
lqw.and(w -> w.like(SysOaProject::getProjectName, kw)
|
||||
.or().like(SysOaProject::getProjectNum, kw)
|
||||
.or().like(SysOaProject::getProjectCode, kw));
|
||||
} else {
|
||||
lqw.like(StringUtils.isNotBlank(bo.getProjectName()), SysOaProject::getProjectName, bo.getProjectName());
|
||||
lqw.like(StringUtils.isNotBlank(bo.getProjectNum()), SysOaProject::getProjectNum, bo.getProjectNum());
|
||||
lqw.like(StringUtils.isNotBlank(bo.getProjectCode()), SysOaProject::getProjectCode, bo.getProjectCode());
|
||||
}
|
||||
//新增生产结项状态筛选
|
||||
lqw.eq(bo.getProductStatus() != null, SysOaProject::getProductStatus, bo.getProductStatus());
|
||||
lqw.eq(bo.getTradeType() != null, SysOaProject::getTradeType, bo.getTradeType());
|
||||
@@ -587,4 +611,37 @@ public class SysOaProjectServiceImpl implements ISysOaProjectService {
|
||||
return baseMapper.getMaxCodeProject(prefix);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OaProjectDashboardVo getProjectDashboard(Long projectId) {
|
||||
SysOaProjectVo project = queryById(projectId);
|
||||
if (project == null) {
|
||||
return null;
|
||||
}
|
||||
List<SysOaTaskVo> tasks = sysOaTaskService.listDashboardTasks(projectId);
|
||||
|
||||
OaProjectScheduleBo scheduleBo = new OaProjectScheduleBo();
|
||||
scheduleBo.setProjectId(projectId);
|
||||
List<OaProjectScheduleVo> schedules = oaProjectScheduleService.queryList(scheduleBo);
|
||||
|
||||
List<OaProjectScheduleStepVo> steps = new ArrayList<>();
|
||||
for (OaProjectScheduleVo sch : schedules) {
|
||||
List<OaProjectScheduleStepVo> part = oaProjectScheduleStepService.selectProjectScheduleStepList(sch.getScheduleId());
|
||||
if (part == null) {
|
||||
continue;
|
||||
}
|
||||
for (OaProjectScheduleStepVo st : part) {
|
||||
st.setProjectId(projectId);
|
||||
st.setProjectName(project.getProjectName());
|
||||
}
|
||||
steps.addAll(part);
|
||||
}
|
||||
|
||||
OaProjectDashboardVo vo = new OaProjectDashboardVo();
|
||||
vo.setProject(project);
|
||||
vo.setTasks(tasks);
|
||||
vo.setSchedules(schedules);
|
||||
vo.setSteps(steps);
|
||||
return vo;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -135,6 +135,11 @@ public class SysOaTaskServiceImpl implements ISysOaTaskService {
|
||||
return baseMapper.listDocumentProject(projectId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SysOaTaskVo> listDashboardTasks(Long projectId) {
|
||||
return baseMapper.selectDashboardTasksByProjectId(projectId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增:自定义查询任务列表(Plus版)
|
||||
*/
|
||||
|
||||
@@ -5,7 +5,6 @@ import com.alibaba.fastjson2.JSONArray;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.ruoyi.oa.domain.OaExpress;
|
||||
import com.ruoyi.oa.domain.vo.OaExpressVo;
|
||||
import sun.misc.BASE64Encoder;
|
||||
import com.ruoyi.common.utils.DateUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
|
||||
@@ -204,8 +204,8 @@
|
||||
status,
|
||||
header
|
||||
from oa_project_schedule_step opss
|
||||
WHERE schedule_id = #{scheduleId}
|
||||
AND step_order = #{currentStep}
|
||||
WHERE opss.schedule_id = #{scheduleId}
|
||||
AND opss.step_order = #{currentStep}
|
||||
and use_flag = '1'
|
||||
AND del_flag = '0'
|
||||
</select>
|
||||
@@ -258,5 +258,29 @@
|
||||
${ew.customSqlSegment}
|
||||
</select>
|
||||
|
||||
<!--
|
||||
综合看板:按 schedule_id 查询步骤列表
|
||||
要求:
|
||||
- 删除 del_flag(表无该字段)
|
||||
- 不使用 opss.* 前缀(不定义别名)
|
||||
- 仅保留 WHERE schedule_id = #{scheduleId}
|
||||
-->
|
||||
<select id="selectProjectScheduleStepList"
|
||||
parameterType="com.ruoyi.oa.domain.OaProjectScheduleStep"
|
||||
resultMap="OaProjectScheduleStepResult">
|
||||
SELECT
|
||||
track_id, accessory, schedule_id, step_order, step_name,
|
||||
plan_start, plan_end, actual_start, actual_end, status,
|
||||
header, use_flag, batch_id, tab_node,
|
||||
first_level_node, second_level_node,
|
||||
start_time, original_end_time, end_time,
|
||||
node_header, related_docs, related_images,
|
||||
specification, sort_num, supplier_id,
|
||||
requirement_file, other,
|
||||
create_by, create_time, update_by, update_time
|
||||
FROM oa_project_schedule_step
|
||||
WHERE schedule_id = #{scheduleId}
|
||||
</select>
|
||||
|
||||
|
||||
</mapper>
|
||||
|
||||
@@ -474,6 +474,41 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
|
||||
</select>
|
||||
|
||||
<!-- 综合看板:LEFT JOIN 进度步骤 del_flag=0、use_flag=1(与步骤表一致即可展示,不再依赖进度主表 project 联表) -->
|
||||
<select id="selectDashboardTasksByProjectId" resultType="com.ruoyi.oa.domain.vo.SysOaTaskVo">
|
||||
SELECT
|
||||
sot.task_id AS taskId,
|
||||
sot.project_id AS projectId,
|
||||
sop.project_code AS projectCode,
|
||||
sot.task_title AS taskTitle,
|
||||
sot.task_type AS taskType,
|
||||
sot.task_grade AS taskGrade,
|
||||
su1.nick_name AS createUserNickName,
|
||||
su2.nick_name AS workerNickName,
|
||||
sot.state AS state,
|
||||
sot.finish_time AS finishTime,
|
||||
sot.track_id AS trackId,
|
||||
opss.tab_node AS tabNode,
|
||||
opss.first_level_node AS firstLevelNode,
|
||||
opss.second_level_node AS secondLevelNode,
|
||||
opss.step_name AS scheduleStepName,
|
||||
opss.status AS scheduleStatus,
|
||||
opss.plan_start AS schedulePlanStart,
|
||||
opss.plan_end AS schedulePlanEnd,
|
||||
opss.header AS scheduleHeader
|
||||
FROM sys_oa_task sot
|
||||
LEFT JOIN sys_user su1 ON su1.user_id = sot.create_user_id
|
||||
LEFT JOIN sys_user su2 ON su2.user_id = sot.worker_id
|
||||
LEFT JOIN sys_oa_project sop ON sop.project_id = sot.project_id
|
||||
LEFT JOIN oa_project_schedule_step opss
|
||||
ON opss.track_id = sot.track_id
|
||||
AND opss.del_flag = '0'
|
||||
AND opss.use_flag = 1
|
||||
WHERE sot.project_id = #{projectId}
|
||||
AND sot.del_flag = '0'
|
||||
ORDER BY sot.create_time DESC
|
||||
</select>
|
||||
|
||||
<select id="queryListPlus" parameterType="com.ruoyi.oa.domain.bo.SysOaTaskBo" resultType="com.ruoyi.oa.domain.vo.SysOaTaskVo">
|
||||
SELECT
|
||||
task_id AS taskId,
|
||||
|
||||
Reference in New Issue
Block a user