feat(oa): 新增项目进度节点批量插入功能

- 新增 NodeDTO 数据传输对象,用于封装节点信息
- 在 OaProjectScheduleStepMapper 中添加 saveBatch 批量插入方法
- 实现 OaProjectScheduleStepServiceImpl 的 batchInsertNodes 方法
- 新增 TableDataConstantUtil 工具类,提供初始化节点数据- 在 OaProjectScheduleController 中新增 addByProjectId 接口
- 扩展 OaProjectScheduleStep 实体类与 VO/BO 类的字段结构
-优化首次编辑时 endTime 和 originalEndTime 的赋值逻辑
This commit is contained in:
2025-10-21 16:56:13 +08:00
parent ca849102b2
commit 2da9f92395
12 changed files with 691 additions and 2 deletions

View File

@@ -109,4 +109,11 @@ public class OaProjectScheduleController extends BaseController {
@PathVariable Long[] scheduleIds) {
return toAjax(iOaProjectScheduleService.deleteWithValidByIds(Arrays.asList(scheduleIds), true));
}
//新增接口插入项目id
@PostMapping("/addByProjectId")
public R<Void> addByProjectId(@Validated(AddGroup.class) @RequestBody OaProjectScheduleBo bo) {
return toAjax(iOaProjectScheduleService.insertByProjectId(bo));
}
}

View File

@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.Date;
import java.math.BigDecimal;
@@ -84,4 +85,55 @@ public class OaProjectScheduleStep extends BaseEntity {
private Long batchId;
/**
* tab节点
*/
private String tabNode;
/**
* 一级节点(阶段节点)
*/
private String firstLevelNode;
/**
* 二级节点(关键节点)
*/
private String secondLevelNode;
/**
* 开始时间
*/
private LocalDateTime startTime;
/**
* 原定结束时间
*/
private LocalDateTime originalEndTime;
/**
* 结束时间
*/
private LocalDateTime endTime;
/**
* 节点负责人
*/
private String nodeHeader;
/**
* 相关资料
*/
private String relatedDocs;
/**
* 相关图片
*/
private String relatedImages;
/**
* 规范说明
*/
private String specification;
}

View File

@@ -1,11 +1,13 @@
package com.ruoyi.oa.domain.bo;
import com.baomidou.mybatisplus.annotation.TableField;
import com.ruoyi.common.core.validate.AddGroup;
import com.ruoyi.common.core.validate.EditGroup;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.*;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.Date;
@@ -98,4 +100,55 @@ public class OaProjectScheduleStepBo extends BaseEntity {
private Long batchId;
/**
* tab节点
*/
private String tabNode;
/**
* 一级节点(阶段节点)
*/
private String firstLevelNode;
/**
* 二级节点(关键节点)
*/
private String secondLevelNode;
/**
* 开始时间
*/
private LocalDateTime startTime;
/**
* 原定结束时间
*/
private LocalDateTime originalEndTime;
/**
* 结束时间
*/
private LocalDateTime endTime;
/**
* 节点负责人
*/
private String nodeHeader;
/**
* 相关资料
*/
private String relatedDocs;
/**
* 相关图片
*/
private String relatedImages;
/**
* 规范说明
*/
private String specification;
}

View File

@@ -0,0 +1,12 @@
package com.ruoyi.oa.domain.dto;
import lombok.Data;
@Data
public class NodeDTO {
private String tabNode; // tab节点
private String firstLevelNode; // 一级节点
private String secondLevelNode; // 二级节点
private String stepName; // 步骤名称(非空,建议与二级节点名一致)
private String specification; // 规范说明(新增字段)
}

View File

@@ -1,11 +1,15 @@
package com.ruoyi.oa.domain.vo;
import java.time.LocalDateTime;
import java.util.Base64;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import com.ruoyi.common.annotation.ExcelDictFormat;
import com.ruoyi.common.convert.ExcelDictConvert;
import com.ruoyi.common.core.domain.BaseEntity;
import com.ruoyi.oa.domain.bo.OaProjectScheduleStepBo;
import com.ruoyi.system.domain.SysOss;
import lombok.Data;
import java.util.Date;
@@ -20,7 +24,7 @@ import java.util.List;
*/
@Data
@ExcelIgnoreUnannotated
public class OaProjectScheduleStepVo {
public class OaProjectScheduleStepVo extends BaseEntity {
private static final long serialVersionUID = 1L;
@@ -107,4 +111,55 @@ public class OaProjectScheduleStepVo {
*/
private Long batchId;
/**
* tab节点
*/
private String tabNode;
/**
* 一级节点(阶段节点)
*/
private String firstLevelNode;
/**
* 二级节点(关键节点)
*/
private String secondLevelNode;
/**
* 开始时间
*/
private LocalDateTime startTime;
/**
* 原定结束时间
*/
private LocalDateTime originalEndTime;
/**
* 结束时间
*/
private LocalDateTime endTime;
/**
* 节点负责人
*/
private String nodeHeader;
/**
* 相关资料
*/
private String relatedDocs;
/**
* 相关图片
*/
private String relatedImages;
/**
* 规范说明
*/
private String specification;
}

View File

@@ -7,6 +7,9 @@ import com.ruoyi.oa.domain.vo.OaProjectScheduleStepVo;
import com.ruoyi.common.core.mapper.BaseMapperPlus;
import org.apache.ibatis.annotations.Param;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import java.util.List;
/**
* 项目进度步骤跟踪Mapper接口
*
@@ -24,4 +27,6 @@ public interface OaProjectScheduleStepMapper extends BaseMapperPlus<OaProjectSch
void updateByStepAndScheduleId(@Param("currentStep") Long currentStep, @Param("scheduleId") Long scheduleId);
OaProjectScheduleStepVo selectByCurrentStepAndScheduleId(@Param("currentStep") Long currentStep, @Param("scheduleId") Long scheduleId);
void saveBatch(List<OaProjectScheduleStep> entities);
}

View File

@@ -53,4 +53,6 @@ public interface IOaProjectScheduleService {
* @return
*/
boolean complete(OaProjectScheduleBo bo);
Boolean insertByProjectId(OaProjectScheduleBo bo);
}

View File

@@ -1,6 +1,9 @@
package com.ruoyi.oa.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.oa.domain.OaProjectScheduleStep;
import com.ruoyi.oa.domain.bo.BatchBo;
import com.ruoyi.oa.domain.dto.NodeDTO;
import com.ruoyi.oa.domain.vo.OaProjectScheduleStepVo;
import com.ruoyi.oa.domain.bo.OaProjectScheduleStepBo;
import com.ruoyi.common.core.page.TableDataInfo;
@@ -15,7 +18,7 @@ import java.util.List;
* @author hdka
* @date 2025-05-08
*/
public interface IOaProjectScheduleStepService {
public interface IOaProjectScheduleStepService{
/**
* 查询项目进度步骤跟踪
@@ -60,4 +63,6 @@ public interface IOaProjectScheduleStepService {
*/
int changeBatch(BatchBo boList);
void batchInsertNodes(List<NodeDTO> nodeList, Long scheduleId);
}

View File

@@ -2,6 +2,7 @@ package com.ruoyi.oa.service.impl;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.esotericsoftware.minlog.Log;
import com.ruoyi.common.helper.LoginHelper;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.core.page.TableDataInfo;
@@ -13,12 +14,14 @@ import com.ruoyi.oa.domain.OaScheduleTemplate;
import com.ruoyi.oa.domain.OaScheduleTemplateStep;
import com.ruoyi.oa.domain.bo.OaProjectScheduleStepBo;
import com.ruoyi.oa.domain.bo.OaScheduleTemplateStepBo;
import com.ruoyi.oa.domain.dto.NodeDTO;
import com.ruoyi.oa.domain.vo.OaProjectScheduleStepVo;
import com.ruoyi.oa.domain.vo.OaScheduleTemplateStepVo;
import com.ruoyi.oa.domain.vo.OaScheduleTemplateVo;
import com.ruoyi.oa.mapper.OaScheduleTemplateMapper;
import com.ruoyi.oa.service.IOaProjectScheduleStepService;
import com.ruoyi.oa.service.IOaScheduleTemplateStepService;
import com.ruoyi.oa.utils.TableDataConstantUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import com.ruoyi.oa.domain.bo.OaProjectScheduleBo;
@@ -209,4 +212,22 @@ public class OaProjectScheduleServiceImpl implements IOaProjectScheduleService {
}
return updateByBo(bo);
}
@Override
public Boolean insertByProjectId(OaProjectScheduleBo bo) {
OaProjectSchedule add = BeanUtil.toBean(bo, OaProjectSchedule.class);
validEntityBeforeSave(add);
add.setTemplateId(1L);
int insert = baseMapper.insert(add);
if (insert <= 0) {
return false; // 插入失败直接返回
}
Long scheduleId = add.getScheduleId();
if (scheduleId == null) {
throw new RuntimeException("插入项目进度表后未获取到主键");
}
projectScheduleStepService.batchInsertNodes(TableDataConstantUtil.getTableData(), scheduleId);
Log.info("项目进度节点批量插入成功");
return true;
}
}

View File

@@ -3,6 +3,8 @@ package com.ruoyi.oa.service.impl;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruoyi.common.core.mapper.BaseMapperPlus;
import com.ruoyi.common.helper.LoginHelper;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.core.page.TableDataInfo;
@@ -11,8 +13,10 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.oa.domain.OaProjectSchedule;
import com.ruoyi.oa.domain.bo.BatchBo;
import com.ruoyi.oa.domain.dto.NodeDTO;
import com.ruoyi.oa.mapper.OaProjectScheduleMapper;
import lombok.RequiredArgsConstructor;
import org.flowable.job.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import com.ruoyi.oa.domain.bo.OaProjectScheduleStepBo;
import com.ruoyi.oa.domain.vo.OaProjectScheduleStepVo;
@@ -22,6 +26,8 @@ import com.ruoyi.oa.service.IOaProjectScheduleStepService;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
/**
* 项目进度步骤跟踪Service业务层处理
@@ -99,6 +105,12 @@ public class OaProjectScheduleStepServiceImpl implements IOaProjectScheduleStepS
// 除了做更新还需要编辑文件权限将涉及到的所有文件 都涉及到userId
OaProjectScheduleStep update = BeanUtil.toBean(bo, OaProjectScheduleStep.class);
validEntityBeforeSave(update);
//查询end_time结束时间是不是空 如果是空则证明是第一次修改需要给end_time赋值也就是新的结束时间原来结束时间不变
OaProjectScheduleStep oaProjectScheduleStep = baseMapper.selectOne(new LambdaQueryWrapper<OaProjectScheduleStep>().eq(OaProjectScheduleStep::getTrackId, update.getTrackId()));
if (oaProjectScheduleStep.getEndTime() == null) {
update.setEndTime(bo.getEndTime());
update.setOriginalEndTime(bo.getEndTime());
}
return baseMapper.updateById(update) > 0;
}
@@ -187,4 +199,34 @@ public class OaProjectScheduleStepServiceImpl implements IOaProjectScheduleStepS
return flag;
}
/**
* 批量插入节点数据(按表结构约束设置字段值)
* @param nodeList 代码中定义的表格节点数据需包含tab、一二级节点和规范说明
* @param scheduleId 所属项目进度ID非空必须传入
*/
public void batchInsertNodes(List<NodeDTO> nodeList, Long scheduleId) {
// 步骤序号从1开始递增确保与schedule_id、use_flag、batch_id组合唯一
AtomicInteger stepOrder = new AtomicInteger(1);
List<OaProjectScheduleStep> entities = nodeList.stream().map(node -> {
OaProjectScheduleStep step = new OaProjectScheduleStep();
// 1. 必须设置值的四个核心字段
step.setTabNode(node.getTabNode()); // tab节点
step.setFirstLevelNode(node.getFirstLevelNode()); // 一级节点
step.setSecondLevelNode(node.getSecondLevelNode()); // 二级节点
step.setSpecification(node.getSpecification()); // 规范说明从NodeDTO补充此字段
// 2. 表结构中非空字段(必须设置,否则插入失败)
step.setScheduleId(scheduleId); // 所属项目进度ID非空外部传入
step.setStepOrder((long) stepOrder.getAndIncrement()); // 步骤序号(非空,递增生成)
step.setStepName(node.getStepName());// 步骤名称非空从NodeDTO获取建议用二级节点名
return step;
}).collect(Collectors.toList());
// 批量插入数据库
baseMapper.saveBatch(entities);
}
}

View File

@@ -0,0 +1,403 @@
package com.ruoyi.oa.utils;
import com.ruoyi.oa.domain.dto.NodeDTO;
import java.util.Arrays;
import java.util.List;
/**
* 表格数据常量:存储所有需要插入的节点数据(不同表格对应不同的方法)
*/
public class TableDataConstantUtil {
/**
* 示例1自动化设计表格数据
* 包含tab节点、一级节点、二级节点、规范说明
*/
public static List<NodeDTO> getTableData() {
return Arrays.asList(
//自动化设计表
// 技术审查阶段
createNode(
"自动化设计", // tab节点
"一、技术审查", // 一级节点
"接地系统图", // 二级节点
null // 规范说明
),
createNode(
"自动化设计",
"一、技术审查",
"传动单线图",
null
),
createNode(
"自动化设计",
"一、技术审查",
"MCC单线图",
null
),
createNode(
"自动化设计",
"一、技术审查",
"变压器清单",
null
),
createNode(
"自动化设计",
"一、技术审查",
"电气室布置图",
null
),
// 自动化设计阶段
createNode(
"自动化设计",
"一、技术审查",
"操作台面板布置图",
null
),
createNode(
"自动化设计",
"二、自动化设计",
"马达元器件检测清单",
null
),
createNode(
"自动化设计",
"二、自动化设计",
"自动化网络配置图",
null
),
createNode(
"自动化设计",
"二、自动化设计",
"图纸详细设计完成",
null
),
//程序设计提资完成
createNode(
"自动化设计",
"三、程序开发",
"功能说明书",
null
),
createNode(
"自动化设计",
"三、程序开发",
"程序设计",
null
),
createNode(
"自动化设计",
"三、程序开发",
"程序仿真",
null
),
createNode(
"自动化设计",
"三、程序开发",
"程序在线测试",
null
),
createNode(
"自动化设计",
"三、程序开发",
"画面设计",
null
),
//现场调试
createNode(
"自动化设计",
"四、现场调试",
"单动",
null
),
createNode(
"自动化设计",
"四、现场调试",
"传动优化",
null
),
createNode(
"自动化设计",
"四、现场调试",
"联动",
null
),
//考核验证通过
createNode(
"自动化设计",
"五、项目收尾",
null,
null
),
//采购,库房表
// 一、一次配线 阶段
createNode(
"采购、库房",
"一、一次配线",
"采购审核",
"接收由项目部或技术部发出的、经过审核的《物料清单BOM》及技术规范并对其进行采购可行性品牌、货期、替代品、成本评审。"
),
createNode(
"采购、库房",
"一、一次配线",
"采购计划与询价、定标",
"根据项目计划制定《采购作业计划》,向合格供应商进行询价、比价、议价,并最终确定供应商,提交审批。"
),
createNode(
"采购、库房",
"一、一次配线",
"采购订单下达与合同签订",
"向选定的供应商下达正式《采购订单》或签订《采购合同》,明确物料规格、数量、价格、交期、付款方式、验收标准等所有细节。"
),
createNode(
"采购、库房",
"一、一次配线",
"采购过程跟催与交期确认",
"主动、定期地与供应商沟通,跟踪生产/备货进度,确认并确保物料能按承诺日期送达。这是应对长周期物料和避免延期的最关键节点。"
),
createNode(
"采购、库房",
"一、一次配线",
"到货报验与问题处理",
"物料到达后采购员协同库房、质检员IQC对物料进行数量、外观、型号规格的初步核对并处理任何与订单不符的问题如数量短缺、型号错误、损坏等"
),
// 二、库房管理节点 阶段
createNode(
"采购、库房",
"二、库房管理节点",
"进货检验IQC",
"质检人员根据检验标准和物料清单,对送达的物料进行质量检验,包括功能测试、电气参数测量、证件核查等。"
),
createNode(
"采购、库房",
"二、库房管理节点",
"物料入库与上架",
"对通过IQC检验的合格物料办理正式入库手续包括系统数据录入、贴码、分类并放置到指定货位。"
),
createNode(
"采购、库房",
"二、库房管理节点",
"生产领料与发料(齐套性检查)",
"根据生产任务单和BOM为车间准备所需物料。关键环节是进行“齐套性检查”即确认一个订单所需的所有物料是否均已备齐避免生产线因缺料停滞。"
),
createNode(
"采购、库房",
"二、库房管理节点",
"库存盘点与预警",
"定期(如月度、季度)\n" +
"对在库物料进行全面盘点,\n" +
"确保账、物、卡一致。\n" +
"同时对关键物料设置最低库存预警,触发补货机制。\n"
),
//车间设计制造表
// 一、一次线装配 阶段
createNode(
"车间设计制造",
"一、一次线装配",
"图纸审核",
null
),
createNode(
"车间设计制造",
"一、一次线装配",
"安装导轨/安装梁",
"根据布局图安装"
),
createNode(
"车间设计制造",
"一、一次线装配",
"安装元器件",
"安装断路器、接触器、变频器等一次元件。"
),
createNode(
"车间设计制造",
"一、一次线装配",
"母排加工与安装",
"制作并安装铜排或铝排,连接处需搪锡或镀银处理。"
),
createNode(
"车间设计制造",
"一、一次线装配",
"一次线接线",
"使用规定颜色的线缆(通常为黑、棕、灰)连接主回路。"
),
// 二、二次线装配 阶段
createNode(
"车间设计制造",
"二、二次线装配",
"安装端子排、线槽、继电器等二次元件。",
null
),
createNode(
"车间设计制造",
"二、二次线装配",
"下线与套标",
"根据接线图,使用不同颜色的导线(通常为蓝、黄绿、红等)进行测量、裁剪、压接端子并套上打印好的线号管。"
),
createNode(
"车间设计制造",
"二、二次线装配",
"布线与接线",
"将线缆整齐地放入线槽,按照图纸接到对应的端子和元件上。要求横平竖直,牢固可靠。"
),
// 三、调试、检验与包装发货 阶段
createNode(
"车间设计制造",
"三、调试、检验与包装发货",
"接线检查",
"对照图纸进行100%的接线正确性检查。"
),
createNode(
"车间设计制造",
"三、调试、检验与包装发货",
"接地连续性测试",
"确保所有接地连接可靠。"
),
createNode(
"车间设计制造",
"三、调试、检验与包装发货",
"绝缘电阻测试",
"使用兆欧表测量相间、相对地的绝缘电阻,确保符合标准(通常>1MΩ"
),
createNode(
"车间设计制造",
"三、调试、检验与包装发货",
"耐压测试",
"施加高于额定电压的测试电压,持续一定时间,检测是否存在绝缘击穿风险。"
),
createNode(
"车间设计制造",
"三、调试、检验与包装发货",
"功能模拟调试",
"在不接通主电源的情况下,通过外部电源模拟信号,测试控制回路的逻辑是否正确。然后接通主电源,进行空载和带载运行测试。"
),
// 四、清理与包装 阶段
createNode(
"车间设计制造",
"四、清理与包装",
"清理柜内灰尘、线头等。",
null
),
createNode(
"车间设计制造",
"四、清理与包装",
"张贴铭牌、警告标识、一次系统图等。",
null
),
createNode(
"车间设计制造",
"四、清理与包装",
"使用塑料膜、气泡袋、护角、木箱等对产品进行防护包装,防止运输途中损坏。",
null
),
// 五、文件整理与发货 阶段
createNode(
"车间设计制造",
"五、文件整理与发货",
"整理随柜文件,通常包括:合格证、出厂检验报告、电气原理图、接线图、元器件说明书等。",
null
),
createNode(
"车间设计制造",
"五、文件整理与发货",
"安排物流,准时发货给客户。",
null
),
//现场实施设计表
// 四、现场调试 阶段
createNode(
"现场实施设计",
"四、现场调试",
"接地测试",
"条件在计划时间点前完成测试接地电阻值完全符合设计要求通常≤1Ω或按图纸规定测试报告含现场照片、测试仪读数、测试人、时间地点清晰、规范、完整并准时上传至公司项目管理平台。\n" +
"主动发现并解决问题:测试结果初次不合格,但团队能主动、快速地分析原因(如土壤问题、连接点腐蚀等),提出整改方案并实施,最终使电阻值达标。此举避免了项目后期更大的延误和成本。\n" +
"提供优化建议:在测试过程中,发现了设计图中未考虑到的接地隐患,或提出了被采纳的接地系统优化建议,提升了整体安全性"
),
createNode(
"现场实施设计",
"四、现场调试",
"现场接线安装及规范",
"核心目标: 所有电气接线工作100%符合图纸与规范,布线整齐、标识清晰、现场安全整洁,为后续调试奠定坚实的硬件基础,实现“零隐患”移交。\n" +
"考核维度: 正确性、规范性、安全性、进度。"
),
createNode(
"现场实施设计",
"四、现场调试",
"PLC打点",
"核心目标: 高效、准确地验证并确认PLC的每一个输入/输出I/O点与现场对应的传感器、执行器动作完全一致确保硬件层与软件层信号通道100%正确、可靠。\n" +
"考核维度: 准确性、完整性、效率、文档记录。"
),
createNode(
"现场实施设计",
"四、现场调试",
"传动优化",
"核心目标: 通过参数整定、特性调试,使所有传动设备(如变频器、伺服驱动器、直流调速器等)的输出特性完全满足甚至超越工艺要求,确保系统运行平稳、高效、可靠。\n" +
"考核维度: 性能指标、稳定性、效率、技术创新"
),
createNode(
"现场实施设计",
"四、现场调试",
"联动调试",
"核心目标: 在“单动”和“传动优化”完成的基础上,使整个自动化系统按预设的工艺流程、联锁逻辑和安全策略,自动、稳定、可靠地连续运行,实现项目的最终功能。\n" +
"考核维度: 系统稳定性、逻辑正确性、故障率、团队协作、最终用户满意度"
),
// 五、项目收尾 阶段
createNode(
"现场实施设计",
"五、项目收尾",
"收尾",
"核心目标: 成功通过客户或最终用户的正式验收,所有技术指标、性能要求和文档资料均满足合同要求,项目正式移交,并取得关键的验收证明文件。\n" +
"考核维度: 客户满意度、验收一次性通过率、文档完整性、项目尾款触发"
)
);
}
// /**
// * 示例2机械设计表格数据另一组不同的节点
// */
// public static List<NodeDTO> getMechanicalDesignTableData() {
// return Arrays.asList(
// createNode(
// "机械设计",
// "方案设计",
// "初步结构图",
// "需包含关键尺寸及材料选型"
// ),
// createNode(
// "机械设计",
// "详细设计",
// "零件加工图",
// "需标注公差等级及表面处理要求"
// )
// );
// }
/**
* 工具方法快速创建NodeDTO对象
* 步骤名称默认使用二级节点名称(确保非空)
*/
private static NodeDTO createNode(String tabNode, String firstLevel, String secondLevel, String specification) {
NodeDTO node = new NodeDTO();
node.setTabNode(tabNode);
node.setFirstLevelNode(firstLevel);
node.setSecondLevelNode(secondLevel);
node.setSpecification(specification);
node.setStepName(secondLevel); // 步骤名=二级节点名(满足非空约束)
return node;
}
}

View File

@@ -22,6 +22,16 @@
<result property="expectedDays" column="expected_days"/>
<result property="useFlag" column="use_flag"/>
<result property="header" column="header"/>
<result property="tabNode" column="tab_node"/>
<result property="firstLevelNode" column="first_level_node"/>
<result property="secondLevelNode" column="second_level_node"/>
<result property="startTime" column="start_time"/>
<result property="originalEndTime" column="original_end_time"/>
<result property="endTime" column="end_time"/>
<result property="nodeHeader" column="node_header"/>
<result property="relatedDocs" column="related_docs"/>
<result property="relatedImages" column="related_images"/>
<result property="specification" column="specification"/>
<!-- ========== 附件列表:多对一 折叠 ========= -->
<collection property="fileList"
@@ -43,6 +53,28 @@
WHERE a.oss_id = so.oss_id
AND a.user_id = #{userId}) )
</sql>
<insert id="saveBatch">
INSERT INTO oa_project_schedule_step (
schedule_id,
step_order,
step_name,
tab_node,
first_level_node,
second_level_node,
specification
) VALUES
<foreach item="item" index="index" collection="list" separator=",">
(
#{item.scheduleId},
#{item.stepOrder},
#{item.stepName},
#{item.tabNode},
#{item.firstLevelNode},
#{item.secondLevelNode},
#{item.specification}
)
</foreach>
</insert>
<update id="updateByStepAndScheduleId">
UPDATE oa_project_schedule_step