1、定制无权限过滤的项目列表、新增需求接口

This commit is contained in:
2026-02-03 12:49:58 +08:00
parent 9534eef8fd
commit 3a4de30d11
10 changed files with 386 additions and 0 deletions

View File

@@ -138,4 +138,17 @@ public class SimulationDemandController {
return demandService.queryTodoList(req);
}
/**
* 新增需求(无权限过滤)
*
* @param req
* @return
*/
@SysLog("新增需求")
@PostMapping("/addDemandNoPermission")
@Operation(summary = "新增需求", description = "新增需求")
public SdmResponse addDemandNoPermission(@RequestBody @Validated SpdmAddDemandReq req) {
return demandService.addDemandNoPermission(req);
}
}

View File

@@ -1,11 +1,15 @@
package com.sdm.project.controller;
import com.sdm.common.common.SdmResponse;
import com.sdm.common.entity.req.project.SpdmNodeListReq;
import com.sdm.common.log.annotation.SysLog;
import com.sdm.outbridge.mode.GetProcessDataReq;
import com.sdm.outbridge.service.lyric.LyricIntegrateService;
import com.sdm.project.model.req.PushReportReq;
import com.sdm.project.model.req.SpdmAddDemandReq;
import com.sdm.project.model.req.ep.EpProjectQueryReq;
import com.sdm.project.model.req.ep.EpSyncPhaseReq;
import com.sdm.project.service.IDemandService;
import com.sdm.project.service.ILyricInternalService;
import com.sdm.project.service.ISimulationLyricNodeService;
import io.swagger.v3.oas.annotations.Operation;
@@ -14,6 +18,8 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
@RestController
@RequestMapping(value = "/node")
@Tag(name = "利元亨定制节点相关接口", description = "利元亨定制节点相关接口")
@@ -28,6 +34,9 @@ public class SimulationLyricNodeController {
@Autowired
private LyricIntegrateService lyricIntegrateService;
@Resource
private IDemandService demandService;
@GetMapping("/updateApprovalStatus")
@Operation(summary = "仿真节点审批状态更新", description = "仿真节点审批状态更新")
public SdmResponse updateApprovalStatus(@RequestParam(value = "projectName") @Validated String projectName, @RequestParam(value = "workspaceName") @Validated String workspaceName, @RequestParam(value = "approvalStatus") @Validated Integer approvalStatus) {
@@ -167,5 +176,17 @@ public class SimulationLyricNodeController {
return lyricInternalService.queryProjectMember(projectId,queryType,current,size);
}
/**
* 项目列表(无权限过滤)
*
* @param req
* @return
*/
@PostMapping("/listNoPermission")
@Operation(summary = "项目列表", description = "项目列表")
public SdmResponse listNoPermission(@RequestBody SpdmNodeListReq req) {
return lyricInternalService.listNoPermission(req);
}
}

View File

@@ -32,6 +32,8 @@ public interface SimulationDemandMapper extends BaseMapper<SimulationDemand> {
SpdmDemandVo getDemandByName(@Param("tenantId") Long tenantId,@Param("demandName") String demandName);
SpdmDemandVo getDemandByNameNoPermission(@Param("demandName") String demandName);
List<SpdmDemandExtraVo> getDemandExtraList(@Param("demandIdList") List<String> demandIdList);
List<SpdmDemandVo> getDemandListById(@Param("demandIdList") List<String> demandIdList);

View File

@@ -45,9 +45,15 @@ public interface SimulationNodeMapper extends BaseMapper<SimulationNode> {
List<SpdmNodeVo> getNodeList(@Param("nodeType") String nodeType, @Param("nodeSubType") String nodeSubType, @Param("exeStatus") String exeStatus, @Param("nodeCode") String nodeCode,
@Param("manager") String manager, @Param("nodeName") String nodeName, @Param("tenantId") Long tenantId, @Param("pos") int pos, @Param("limit") int limit);
List<SpdmNodeVo> getNodeListNoPermission(@Param("nodeType") String nodeType, @Param("nodeSubType") String nodeSubType, @Param("exeStatus") String exeStatus, @Param("nodeCode") String nodeCode,
@Param("manager") String manager, @Param("nodeName") String nodeName, @Param("tenantId") Long tenantId, @Param("pos") int pos, @Param("limit") int limit);
int getNodeListCount(@Param("nodeType") String nodeType, @Param("nodeSubType") String nodeSubType, @Param("exeStatus") String exeStatus, @Param("nodeCode") String nodeCode,
@Param("manager") String manager, @Param("nodeName") String nodeName, @Param("tenantId") Long tenantId);
int getNodeListCountNoPermission(@Param("nodeType") String nodeType, @Param("nodeSubType") String nodeSubType, @Param("exeStatus") String exeStatus, @Param("nodeCode") String nodeCode,
@Param("manager") String manager, @Param("nodeName") String nodeName, @Param("tenantId") Long tenantId);
List<SpdmNodeExtraVo> getNodeExtraListByNodeIdList(@Param("nodeIdList") List<String> nodeIdList);

View File

@@ -46,4 +46,6 @@ public interface IDemandService {
SdmResponse<PageDataResp<List<FileMetadataInfoResp>>> queryDemandFiles(QueryDirReq req);
SdmResponse queryTodoList(DemandQryReq req);
SdmResponse addDemandNoPermission(SpdmAddDemandReq req);
}

View File

@@ -1,6 +1,7 @@
package com.sdm.project.service;
import com.sdm.common.common.SdmResponse;
import com.sdm.common.entity.req.project.SpdmNodeListReq;
import com.sdm.outbridge.mode.GetProcessDataReq;
import com.sdm.project.model.req.PushReportReq;
import com.sdm.project.model.req.ep.EpProjectQueryReq;
@@ -49,4 +50,6 @@ public interface ILyricInternalService {
/* 同步任务的异常状态 */
SdmResponse syncException();
SdmResponse listNoPermission(SpdmNodeListReq req);
}

View File

@@ -1104,6 +1104,152 @@ public class DemandServiceImpl extends BaseService implements IDemandService {
return SdmResponse.success(demandVoList);
}
@Transactional
@Override
public SdmResponse addDemandNoPermission(SpdmAddDemandReq req) {
Long tenantId = ThreadLocalContext.getTenantId();
Long jobNumber = ThreadLocalContext.getUserId();
req.setCreator(jobNumber);
log.info("新增需求时无权限校验当前租户id为{},工号为:{}", tenantId, jobNumber);
// 获取仿真负责人
String pMemberList = req.getPMemberList();
// 获取仿真执行人
String eMemberList = req.getEMemberList();
// 3D负责人
String threeDMemberList = req.getTMemberList();
// 关注人
String attentionMemberList = req.getAMemberList();
// 获取需求额外属性
List<SpdmDemandExtraReq> demandExtraList = req.getExtras();
String curDateStr = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
req.setCreateTime(curDateStr);
req.setUuid(RandomUtil.generateString(32));
SpdmDemandVo demandByName = mapper.getDemandByNameNoPermission(req.getDemandName());
if (ObjectUtils.isNotEmpty(demandByName)) {
return SdmResponse.failed("需求名称:" + demandByName.getDemandName() + "已存在,请修改");
}
if (mapper.addDemand(req, tenantId, jobNumber) <= 0) {
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
return SdmResponse.failed("新增需求失败!");
}
long demandId = req.getId();
log.info("需求主键id为无权限校验{}", demandId);
List<SpdmDemandRelateMemberReq> allMemberList = new ArrayList<>();
String uuid = req.getUuid();
if (StringUtils.isNotBlank(pMemberList)) {
String[] pMemberArray = pMemberList.split(",");
for (String userId : pMemberArray) {
SpdmDemandRelateMemberReq spdmDemandRelateMemberReq = new SpdmDemandRelateMemberReq();
spdmDemandRelateMemberReq.setDemandId(uuid);
spdmDemandRelateMemberReq.setType(0);
spdmDemandRelateMemberReq.setUserId(Long.valueOf(userId));
spdmDemandRelateMemberReq.setCreateTime(curDateStr);
spdmDemandRelateMemberReq.setCreator(jobNumber);
allMemberList.add(spdmDemandRelateMemberReq);
}
}
if (StringUtils.isNotBlank(eMemberList)) {
String[] eMemberArray = eMemberList.split(",");
for (String userId : eMemberArray) {
SpdmDemandRelateMemberReq spdmDemandRelateMemberReq = new SpdmDemandRelateMemberReq();
spdmDemandRelateMemberReq.setDemandId(uuid);
spdmDemandRelateMemberReq.setType(1);
spdmDemandRelateMemberReq.setUserId(Long.valueOf(userId));
spdmDemandRelateMemberReq.setCreateTime(curDateStr);
spdmDemandRelateMemberReq.setCreator(jobNumber);
allMemberList.add(spdmDemandRelateMemberReq);
}
}
if (StringUtils.isNotBlank(threeDMemberList)) {
String[] threeDMemberArray = threeDMemberList.split(",");
for (String userId : threeDMemberArray) {
SpdmDemandRelateMemberReq spdmDemandRelateMemberReq = new SpdmDemandRelateMemberReq();
spdmDemandRelateMemberReq.setDemandId(uuid);
spdmDemandRelateMemberReq.setType(2);
spdmDemandRelateMemberReq.setUserId(Long.valueOf(userId));
spdmDemandRelateMemberReq.setCreateTime(curDateStr);
spdmDemandRelateMemberReq.setCreator(jobNumber);
allMemberList.add(spdmDemandRelateMemberReq);
}
}
if (StringUtils.isNotBlank(attentionMemberList)) {
String[] attentionMemberArray = attentionMemberList.split(",");
for (String userId : attentionMemberArray) {
SpdmDemandRelateMemberReq spdmDemandRelateMemberReq = new SpdmDemandRelateMemberReq();
spdmDemandRelateMemberReq.setDemandId(uuid);
spdmDemandRelateMemberReq.setType(3);
spdmDemandRelateMemberReq.setUserId(Long.valueOf(userId));
spdmDemandRelateMemberReq.setCreateTime(curDateStr);
spdmDemandRelateMemberReq.setCreator(jobNumber);
allMemberList.add(spdmDemandRelateMemberReq);
}
}
if (CollectionUtils.isNotEmpty(allMemberList)) {
if (mapper.addDemandMember(allMemberList) <= 0) {
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
return SdmResponse.failed("新增需求关联成员失败!");
}
}
if (CollectionUtils.isNotEmpty(demandExtraList)) {
demandExtraList.forEach(demandExtra -> {
demandExtra.setDemandId(req.getUuid());
demandExtra.setCreateTime(curDateStr);
demandExtra.setCreator(jobNumber);
});
if (mapper.addDemandExtra(demandExtraList) <= 0) {
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
return SdmResponse.failed("新增需求额外属性失败!");
}
}
BatchCreateNormalDirReq batchCreateNormalDirReq = new BatchCreateNormalDirReq();
batchCreateNormalDirReq.setParentUUId(req.getProjectId());
FolderItemReq folderItemReq = new FolderItemReq();
folderItemReq.setFolderName(req.getDemandName());
folderItemReq.setFolderUuid(req.getUuid());
batchCreateNormalDirReq.setFolderItems(Collections.singletonList(folderItemReq));
batchCreateNormalDirReq.setSkipPermissionCheck(true);
log.info("创建需求文件夹参数(无权限校验): {}", batchCreateNormalDirReq);
SdmResponse dirCreateResp = dataFeignClient.batchCreateNormalDirs(batchCreateNormalDirReq);
if (ObjectUtils.isEmpty(dirCreateResp) || dirCreateResp.getCode() != ResultCode.SUCCESS.getCode()) {
log.error("创建项目:{}下的{}需求文件夹(无权限校验)时,创建文件夹失败,原因为:{}", req.getProjectId(),req.getDemandName(), dirCreateResp.getMessage());
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
return SdmResponse.failed("您没有选择项目的相应权限,请更换其他项目进行创建");
}
log.info("创建需求文件夹响应(无权限校验): {}", dirCreateResp);
// 更新需求创建人对需求文件夹的权限 & 更新需求仿真负责人(确认人)对需求文件夹的权限(预览、下载)
Long userId = ThreadLocalContext.getUserId();
UpdatePermissionReq updatePermissionReq = new UpdatePermissionReq();
updatePermissionReq.setUuid(uuid);
Map<Long, Byte> userPermissions = new HashMap<>();
// 创建人
userPermissions.put(userId, FilePermissionEnum.ALL.getValue());
// 仿真负责人
if (CollectionUtils.isNotEmpty(allMemberList)) {
allMemberList.stream().filter(member -> MemberTypeEnum.PRINCIPAL.getCode().equals(member.getType())).forEach(member -> {
userPermissions.put(member.getUserId(), FilePermissionEnum.BASE.getValue());
});
}
updatePermissionReq.setUserPermissions(userPermissions);
log.info("创建需求时(无权限校验),更新需求创建人和需求仿真负责人(确认人)权限的参数为:{}",updatePermissionReq);
SdmResponse updatePermissionResponse = dataFeignClient.updatePermission(updatePermissionReq);
log.info("创建需求时(无权限校验),更新需求创建人和需求仿真负责人(确认人)权限的返回值为:{}",updatePermissionResponse);
// 只有利元亨需要在创建需求的同时创建任务
if (req.getIsLyric()) {
SimulationDemand demand = new SimulationDemand();
BeanUtils.copyProperties(req, demand);
simulationTaskService.batchCreateTaskFromDemand(Collections.singletonList(demand));
}
return SdmResponse.success(req.getUuid());
}
private String getLastNodeId(TaskNode taskNode) {
List<String> tagListProperty;
String lastNodeId = "";

View File

@@ -9,10 +9,12 @@ import com.sdm.common.entity.enums.DirTypeEnum;
import com.sdm.common.entity.enums.FilePermissionEnum;
import com.sdm.common.entity.enums.NodeTypeEnum;
import com.sdm.common.entity.req.data.*;
import com.sdm.common.entity.req.project.SpdmNodeListReq;
import com.sdm.common.entity.req.system.UserQueryReq;
import com.sdm.common.entity.resp.system.CIDUserResp;
import com.sdm.common.feign.impl.data.DataClientFeignClientImpl;
import com.sdm.common.feign.impl.system.SysUserFeignClientImpl;
import com.sdm.common.log.CoreLogger;
import com.sdm.common.utils.FilesUtil;
import com.sdm.common.utils.MdcUtil;
import com.sdm.common.utils.PageUtils;
@@ -37,6 +39,9 @@ import com.sdm.project.model.req.*;
import com.sdm.project.model.req.ep.EpProjectQueryReq;
import com.sdm.project.model.req.ep.EpSyncPhaseReq;
import com.sdm.project.model.vo.SpdmDemandVo;
import com.sdm.project.model.vo.SpdmNodeExtraVo;
import com.sdm.project.model.vo.SpdmNodeMemberVo;
import com.sdm.project.model.vo.SpdmNodeVo;
import com.sdm.project.service.ILyricInternalService;
import com.sdm.project.service.INodeService;
import com.sdm.project.service.ISimulationTaskService;
@@ -64,6 +69,7 @@ import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
@@ -1787,6 +1793,132 @@ public class LyricInternalServiceImpl implements ILyricInternalService {
}
@Override
public SdmResponse listNoPermission(SpdmNodeListReq req) {
int pos = (req.getCurrent() - 1) * req.getSize();
int limit = req.getSize();
Long tenantId = ThreadLocalContext.getTenantId();
List<SpdmNodeVo> nodeList = nodeMapper.getNodeListNoPermission(req.getNodeType(), req.getNodeSubType(), req.getExeStatus(), req.getNodeCode(), req.getManager(), req.getNodeName(),
tenantId, pos, limit);
CoreLogger.info("getNodeList param:{},tenantId:{}", JSONObject.toJSONString(req), tenantId);
if (CollectionUtils.isEmpty(nodeList)) {
JSONObject jsonObject = new JSONObject();
jsonObject.put("data", nodeList);
jsonObject.put("total", 0);
return SdmResponse.success(jsonObject);
}
int total = nodeMapper.getNodeListCountNoPermission(req.getNodeType(), req.getNodeSubType(), req.getExeStatus(), req.getNodeCode(), req.getManager(), req.getNodeName(), ThreadLocalContext.getTenantId());
log.info("总数为:{}", total);
Integer progressStatus;
Integer achieveStatus;
// 查询节点的额外属性
List<String> nodeIdList = nodeList.stream().map(SpdmNodeVo::getUuid).toList();
List<SpdmNodeMemberVo> spdmNodeMemberVoList = nodeMapper.getNodeMemberListByNodeIdList(nodeIdList);
if (CollectionUtils.isNotEmpty(spdmNodeMemberVoList)) {
List<Long> usewrIdList = spdmNodeMemberVoList.stream().map(SpdmNodeMemberVo::getUserId).distinct().toList();
SdmResponse<List<CIDUserResp>> cidUserResp = sysUserFeignClient.listUserByIds(UserQueryReq.builder().userIds(usewrIdList).build());
List<CIDUserResp> userList = cidUserResp.getData();
Map<Long, List<CIDUserResp>> userMap = Map.of();
if (CollectionUtils.isNotEmpty(userList)) {
userMap = userList.stream().collect(Collectors.groupingBy(CIDUserResp::getUserId));
}
String nodeId;
// 关联到节点上
Map<String, List<SpdmNodeMemberVo>> nodeMemberMap = spdmNodeMemberVoList.stream().collect(Collectors.groupingBy(SpdmNodeMemberVo::getNodeId));
for (Map.Entry<String, List<SpdmNodeMemberVo>> nodeMemberEntry : nodeMemberMap.entrySet()) {
List<CIDUserResp> memberList = new ArrayList<>();
nodeId = nodeMemberEntry.getKey();
for (SpdmNodeVo spdmNodeVo : nodeList) {
if (nodeId.equals(spdmNodeVo.getUuid())) {
for (SpdmNodeMemberVo spdmNodeMemberVo : nodeMemberEntry.getValue()) {
if (CollectionUtils.isNotEmpty(userMap.get(spdmNodeMemberVo.getUserId()))) {
memberList.add(userMap.get(spdmNodeMemberVo.getUserId()).get(0));
}
}
spdmNodeVo.setMemberList(memberList);
}
}
}
}
List<SpdmNodeExtraVo> spdmNodeExtraVoList = nodeMapper.getNodeExtraListByNodeIdList(nodeIdList);
if (CollectionUtils.isNotEmpty(spdmNodeExtraVoList)) {
String nodeId;
// 关联到节点上
Map<String, List<SpdmNodeExtraVo>> nodeExtraMap = spdmNodeExtraVoList.stream().collect(Collectors.groupingBy(SpdmNodeExtraVo::getNodeId));
for (Map.Entry<String, List<SpdmNodeExtraVo>> nodeExtraEntry : nodeExtraMap.entrySet()) {
nodeId = nodeExtraEntry.getKey();
for (SpdmNodeVo spdmNodeVo : nodeList) {
if (nodeId.equals(spdmNodeVo.getUuid())) {
spdmNodeVo.setExtras(nodeExtraEntry.getValue());
}
}
}
}
List<Long> userIdList = nodeList.stream().filter(node -> ObjectUtils.isNotEmpty(node.getCreator())).map(SpdmNodeVo::getCreator)
.toList();
Map<Long, CIDUserResp> userMap = new HashMap<>();
if (CollectionUtils.isNotEmpty(userIdList)) {
SdmResponse<List<CIDUserResp>> listSdmResponse = sysUserFeignClient.listUserByIds(UserQueryReq.builder().userIds(userIdList.stream().distinct().toList()).build());
if (listSdmResponse.isSuccess() && CollectionUtils.isNotEmpty(listSdmResponse.getData())) {
userMap = listSdmResponse.getData().stream().collect(Collectors.toMap(CIDUserResp::getUserId, Function.identity()));
}
}
for (SpdmNodeVo spdmNodeVo : nodeList) {
// TODO 转换项目进度状态
progressStatus = spdmNodeVo.getProgress();
if (ObjectUtils.isNotEmpty(progressStatus)) {
switch (progressStatus) {
case 0:
spdmNodeVo.setProgressStatusValue("未开始");
break;
case 1:
spdmNodeVo.setProgressStatusValue("进行中");
break;
case 2:
spdmNodeVo.setProgressStatusValue("已完成");
break;
default:
spdmNodeVo.setProgressStatusValue("未知");
break;
}
}
// TODO 项目达成状态(红黄绿灯)
achieveStatus = spdmNodeVo.getAchieveStatus();
if (ObjectUtils.isNotEmpty(achieveStatus)) {
switch (achieveStatus) {
case 1:
spdmNodeVo.setAchieveStatusValue("red");
break;
case 2:
spdmNodeVo.setProgressStatusValue("yellow");
break;
case 3:
spdmNodeVo.setProgressStatusValue("grey");
break;
case 4:
spdmNodeVo.setProgressStatusValue("grey");
break;
default:
spdmNodeVo.setProgressStatusValue("unknown");
break;
}
}
Long creator = spdmNodeVo.getCreator();
if (ObjectUtils.isNotEmpty(creator)) {
spdmNodeVo.setCreatorObj(userMap.get(creator));
}
}
JSONObject jsonObject = new JSONObject();
jsonObject.put("data", nodeList);
jsonObject.put("total", total);
return SdmResponse.success(jsonObject);
}
private SdmResponse httpSyncTodoData( List<SimulationNode> projectNodeList,List<LyricVTodoEmulationInfoDM> todoInfoList){
String traceId = MdcUtil.getTraceId();
CompletableFuture<SdmResponse> syncTodoDataFeature = CompletableFuture.supplyAsync(() ->

View File

@@ -153,6 +153,10 @@
select * from simulation_demand where tenant_id = #{tenantId} and demand_name = #{demandName} limit 1
</select>
<select id="getDemandByNameNoPermission" resultType="com.sdm.project.model.vo.SpdmDemandVo">
select * from simulation_demand where demand_name = #{demandName} limit 1
</select>
<select id="getDemandExtraList" resultType="com.sdm.project.model.vo.SpdmDemandExtraVo">
select * from simulation_demand_extra where demand_id in (
<foreach collection='demandIdList' item='demandId' index='index' separator=','>

View File

@@ -281,6 +281,63 @@
</if>
</select>
<select id="getNodeListNoPermission" resultType="com.sdm.project.model.vo.SpdmNodeVo">
select * from simulation_node sn
<where>
<if test="nodeType != null and nodeType != ''">
sn.nodeType = #{nodeType} and
</if>
<if test="nodeSubType != null and nodeSubType != ''">
sn.nodeSubType = #{nodeSubType} and
</if>
<if test="exeStatus != null and exeStatus != ''">
sn.exe_status = #{exeStatus} and
</if>
<if test="nodeCode != null and nodeCode != ''">
<bind name="searchKey1" value="'%' + nodeCode + '%'"/>
sn.nodeCode like #{searchKey1} and
</if>
<if test="manager != null and manager != ''">
<bind name="searchKey2" value="'%' + manager + '%'"/>
snm.name like #{searchKey2} and
</if>
<if test="nodeName != null and nodeName != ''">
<bind name="searchKey3" value="'%' + nodeName + '%'"/>
sn.nodeName like #{searchKey3} and
</if>
</where>
order by create_time desc
limit #{pos},#{limit}
</select>
<select id="getNodeListCountNoPermission" resultType="java.lang.Integer">
select count(1) from simulation_node sn
<where>
<if test="nodeType != null and nodeType != ''">
sn.nodeType = #{nodeType} and
</if>
<if test="nodeSubType != null and nodeSubType != ''">
sn.nodeSubType = #{nodeSubType} and
</if>
<if test="exeStatus != null and exeStatus != ''">
sn.exe_status = #{exeStatus} and
</if>
<if test="nodeCode != null and nodeCode != ''">
<bind name="searchKey1" value="'%' + nodeCode + '%'"/>
sn.nodeCode like #{searchKey1} and
</if>
<if test="manager != null and manager != ''">
<bind name="searchKey2" value="'%' + manager + '%'"/>
snm.name like #{searchKey2} and
</if>
<if test="nodeName != null and nodeName != ''">
<bind name="searchKey3" value="'%' + nodeName + '%'"/>
sn.nodeName like #{searchKey3} and
</if>
</where>
</select>
<select id="getNodeExtraListByNodeIdList" resultType="com.sdm.project.model.vo.SpdmNodeExtraVo">
SELECT
*