feat(项目看板): 新增项目综合看板功能

新增项目综合看板功能,聚合展示项目、任务、进度主表和步骤数据
- 新增后端聚合接口 GET /oa/project/dashboard/{projectId}
- 新增前端看板页面,包含项目列表、任务表格和进度导图
- 优化思维导图组件,支持看板模式下的紧凑展示
- 新增进度明细表格视图和状态图例
- 实现任务与进度步骤的关联展示
- 添加项目模糊搜索功能
This commit is contained in:
2026-04-15 17:19:56 +08:00
parent 5d4794c9bd
commit 50f3f15f48
24 changed files with 1623 additions and 115 deletions

View File

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

View File

@@ -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);
}
/**
* 获取项目管理详细信息
*

View File

@@ -201,6 +201,12 @@ public class SysOaProjectBo extends BaseEntity {
private Long customerId;
//客户名称
private String customerName;
/**
* 综合模糊查询(名称 / 编号 / 代号 任一匹配),与 projectName、projectNum、projectCode 互斥:有值时优先使用本字段
*/
private String keyword;
//是否置顶
private Integer isTop;

View File

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

View File

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

View File

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

View File

@@ -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 集合

View File

@@ -46,6 +46,11 @@ public interface SysOaTaskMapper extends BaseMapperPlus<SysOaTaskMapper, SysOaTa
List<SysOaTaskVo> listDocumentProject(Long projectId);
/**
* 综合看板:某项目下任务(一行一条任务)
*/
List<SysOaTaskVo> selectDashboardTasksByProjectId(@Param("projectId") Long projectId);
/**
* 新增自定义查询任务列表Plus版
*/

View File

@@ -38,6 +38,11 @@ public interface IOaProjectScheduleStepService{
*/
List<OaProjectScheduleStepVo> queryList(OaProjectScheduleStepBo bo);
/**
* 按 scheduleId 查询进度步骤列表(综合看板聚合接口使用)
*/
List<OaProjectScheduleStepVo> selectProjectScheduleStepList(Long scheduleId);
/**
* 新增项目进度步骤跟踪
*/

View File

@@ -103,4 +103,9 @@ public interface ISysOaProjectService {
Boolean postponeProject(SysOaProject bo);
SysOaProjectVo getMaxCode(String prefix);
/**
* 综合看板:项目详情 + 任务 + 进度主表 + 进度步骤(一次返回)
*/
OaProjectDashboardVo getProjectDashboard(Long projectId);
}

View File

@@ -109,6 +109,11 @@ public interface ISysOaTaskService {
* @return
*/
List<SysOaTaskVo> listDocumentProject(Long projectId);
/**
* 综合看板任务列表(完整字段,无 task_item 重复行)
*/
List<SysOaTaskVo> listDashboardTasks(Long projectId);
/**
* 新增自定义查询任务列表Plus版
*/

View File

@@ -68,7 +68,8 @@ public class OaProjectScheduleServiceImpl implements IOaProjectScheduleService {
*/
@Override
public TableDataInfo<OaProjectScheduleVo> queryPageList(OaProjectScheduleBo bo, PageQuery pageQuery) {
QueryWrapper<OaProjectSchedule> lqw = buildQueryWrapper(bo);
// 分页列表走自定义 Join SQLXML 中存在 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 默认 SQLFROM oa_project_schedule
* 仅使用 oa_project_schedule 表字段,严格对齐表结构:
* - oa_project_scheduleproject_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;
}
/**
* 新增项目进度
*/

View File

@@ -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 trueXML 中带 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());
}
/**
* 新增项目进度步骤跟踪
*/

View File

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

View File

@@ -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版
*/

View File

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

View File

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

View File

@@ -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,