[add] 接入萤石摄像头,新增子项目和摄像头预置位相关逻辑 [update] 修改geojson中方阵等重新上传逻辑

This commit is contained in:
lcj
2025-06-13 18:28:31 +08:00
parent fbea1c2c2a
commit 784c7c0783
63 changed files with 3072 additions and 341 deletions

View File

@ -1,15 +1,33 @@
package org.dromara.facility.constant;
import java.util.List;
/**
* @author lcj
* @date 2025/5/27 18:27
*/
public interface FacRedisKeyConstant {
String FAC_REDIS_PREFIX = "fac:";
/**
* 设施模块 Redis 缓存前缀
*/
String FAC_REDIS_PREFIX = "fac:facility:";
/**
* 设施模块正在操作任务 Redis 缓存前缀
*/
String FAC_IN_OPERATION_REDIS_KEY_PREFIX = FAC_REDIS_PREFIX + "inOperation:";
/**
* 设施模块类型 - 坐标
*/
String GEO_TYPE_LOCAL = "location";
/**
* 设施模块类型 - 名称
*/
String GEO_TYPE_NAME = "name";
/**
* 批量上传桩点、支架、立柱 Redis 缓存 key
*
@ -18,17 +36,62 @@ public interface FacRedisKeyConstant {
* @return Redis 缓存 key
*/
static String getBatchUploadPartsRedisKey(String sessionId, int batchNum) {
return String.format("%s%s:%s:%s", FAC_REDIS_PREFIX, "panel:parts", sessionId, batchNum);
return String.format("%s%s:%s:%s", FAC_REDIS_PREFIX, "parts", sessionId, batchNum);
}
/**
* 当前项目是否正在操作 Redis 缓存 key
* 批量上传光伏板 Redis 缓存 key
*
* @param sessionId 唯一标识
* @param batchNum 第几批数据
* @param type 类型
* @return Redis 缓存 key
*/
static String getBatchUploadPanelRedisKey(String sessionId, int batchNum, String type) {
return String.format("%s%s:%s:%s:%s", FAC_REDIS_PREFIX, "panel", sessionId, batchNum, type);
}
/**
* 项目内进行中的任务 Redis 缓存 key 前缀
*
* @param projectId 项目 ID
* @return Redis 缓存前缀
*/
static String getInOperationByProjectRedisPrefix(Long projectId) {
return String.format("%s%s:%s:", FAC_IN_OPERATION_REDIS_KEY_PREFIX, "project", projectId);
}
/**
* 当前项目下是否正在操作桩点、支架、立柱 Redis 缓存 key
*
* @param projectId 项目 ID
* @return Redis 缓存 key
*/
static String getInOperationByProjectRedisKey(Long projectId) {
return String.format("%s%s:%s", FAC_IN_OPERATION_REDIS_KEY_PREFIX, "project", projectId);
static String getPartsInOperationByProjectRedisKey(Long projectId) {
return String.format("%s%s", getInOperationByProjectRedisPrefix(projectId), "parts");
}
/**
* 当前项目下是否正在操作光伏板 Redis 缓存 key
*
* @param projectId 项目 ID
* @return Redis 缓存 key
*/
static String getPanelInOperationByProjectRedisKey(Long projectId) {
return String.format("%s%s", getInOperationByProjectRedisPrefix(projectId), "panel");
}
/**
* 获取操作的 Redis 缓存 key 列表
*
* @param projectId 项目 ID
* @return Redis 缓存 key 列表
*/
static List<String> getInOperationRedisKeyList(Long projectId) {
return List.of(
getPartsInOperationByProjectRedisKey(projectId),
getPanelInOperationByProjectRedisKey(projectId)
);
}
}

View File

@ -1,22 +0,0 @@
package org.dromara.facility.domain.dto.geojson;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author lcj
* @date 2025/4/24 10:40
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class FacFeatureByLine {
private String type;
private FacGeometryByLine geometry;
private FacProperties properties;
}

View File

@ -4,6 +4,9 @@ import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serial;
import java.io.Serializable;
/**
* @author lcj
* @date 2025/4/24 10:32
@ -11,7 +14,10 @@ import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class FacFeatureByPlane {
public class FacFeatureByPlane implements Serializable {
@Serial
private static final long serialVersionUID = 6732054357362738399L;
private String type;

View File

@ -1,25 +0,0 @@
package org.dromara.facility.domain.dto.geojson;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.List;
/**
* @author lcj
* @date 2025/4/24 10:38
*/
@Data
public class FacGeoJsonByLine implements Serializable {
@Serial
private static final long serialVersionUID = -1019429627483913266L;
private String name;
private String type;
private List<FacFeatureByLine> features;
}

View File

@ -1,24 +0,0 @@
package org.dromara.facility.domain.dto.geojson;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
/**
* @author lcj
* @date 2025/4/24 10:41
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class FacGeometryByLine {
private String type;
private List<List<Double>> coordinates;
private Long id;
}

View File

@ -4,6 +4,8 @@ import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serial;
import java.io.Serializable;
import java.util.List;
/**
@ -13,7 +15,10 @@ import java.util.List;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class FacGeometryByPlane {
public class FacGeometryByPlane implements Serializable {
@Serial
private static final long serialVersionUID = -82255764789167107L;
private String type;

View File

@ -33,4 +33,19 @@ public class FacPhotovoltaicPanelCreateByGeoJsonReq implements Serializable {
*/
private List<FacGeoJsonByPoint> nameGeoJson;
/**
* 批次上传标识
*/
private String sessionId;
/**
* 当前批次
*/
private int batchNum;
/**
* 总批次
*/
private int totalBatch;
}

View File

@ -0,0 +1,28 @@
package org.dromara.facility.domain.vo.matrix;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* @author lcj
* @date 2025/6/10 15:09
*/
@Data
public class FacMatrixBySubProjectVo implements Serializable {
@Serial
private static final long serialVersionUID = -3427826315362519128L;
/**
* 主键
*/
private Long matrixId;
/**
* 方阵名称
*/
private String name;
}

View File

@ -146,12 +146,14 @@ public class FacBoxTransformerServiceImpl extends ServiceImpl<FacBoxTransformerM
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean insertByGeoJson(FacBoxTransformerCreateByGeoJsonReq geoJson) {
Long projectId = geoJson.getProjectId();
// Long projectId = geoJson.getProjectId();
Long projectId = 1930896467736707073L;
if (projectService.getById(projectId) == null) {
throw new ServiceException("项目不存在", HttpStatus.NOT_FOUND);
}
// 获取当前项目下方阵信息
List<FacMatrix> matrixList = matrixService.lambdaQuery()
.select(FacMatrix::getId, FacMatrix::getPositions)
.eq(FacMatrix::getProjectId, projectId).list();
if (CollUtil.isEmpty(matrixList)) {
throw new ServiceException("项目下无方阵数据,请先创建方阵信息后再添加箱变信息", HttpStatus.NOT_FOUND);

View File

@ -146,12 +146,14 @@ public class FacInverterServiceImpl extends ServiceImpl<FacInverterMapper, FacIn
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean insertByGeoJson(FacInverterCreateByGeoJsonReq geoJson) {
Long projectId = geoJson.getProjectId();
// Long projectId = geoJson.getProjectId();
Long projectId = 1930896467736707073L;
if (projectService.getById(projectId) == null) {
throw new ServiceException("项目不存在", HttpStatus.NOT_FOUND);
}
// 获取当前项目下方阵信息
List<FacMatrix> matrixList = matrixService.lambdaQuery()
.select(FacMatrix::getId, FacMatrix::getPositions)
.eq(FacMatrix::getProjectId, projectId).list();
if (CollUtil.isEmpty(matrixList)) {
throw new ServiceException("项目下无方阵数据,请先创建方阵信息后再添加逆变器信息", HttpStatus.NOT_FOUND);

View File

@ -35,6 +35,7 @@ import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
/**
* 设施-方阵Service业务层处理
@ -257,19 +258,21 @@ public class FacMatrixServiceImpl extends ServiceImpl<FacMatrixMapper, FacMatrix
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean insertByGeoJson(FacMatrixCreateByGeoJsonReq geoJson) {
// 判断当前项目是否正在执行桩点、立柱、支架数据
String operationRedisKey = FacRedisKeyConstant.getInOperationByProjectRedisKey(geoJson.getProjectId());
// Long projectId = geoJson.getProjectId();
Long projectId = 1930896467736707073L;
// 判断 redis key 是否存在,存在则返回
Object object = redisTemplate.opsForValue().get(operationRedisKey);
if (object != null && (Boolean) object) {
throw new ServiceException("项目下桩点、立柱、支架数据正在处理中,请等待处理完毕后操作", HttpStatus.BAD_REQUEST);
List<String> operationRedisKey = FacRedisKeyConstant.getInOperationRedisKeyList(projectId);
List<Object> list = redisTemplate.opsForValue().multiGet(operationRedisKey);
boolean hasValue = list != null && list.stream().anyMatch(Objects::nonNull);
if (hasValue) {
throw new ServiceException("项目下有设施数据正在处理中,请等待处理完毕后再操作", HttpStatus.BAD_REQUEST);
}
Long projectId = geoJson.getProjectId();
if (projectService.getById(projectId) == null) {
throw new ServiceException("项目不存在", HttpStatus.NOT_FOUND);
}
// 获取当前项目下方阵信息
List<FacMatrix> oldMatrixList = this.lambdaQuery()
.select(FacMatrix::getId)
.eq(FacMatrix::getProjectId, projectId).list();
List<FacMatrix> matrixList = new ArrayList<>();
List<FacGeoJson> locationGeoJsonList = geoJson.getLocationGeoJson();
@ -303,33 +306,23 @@ public class FacMatrixServiceImpl extends ServiceImpl<FacMatrixMapper, FacMatrix
matrixList.add(matrix);
}
// todo 关联数据处理
if (CollUtil.isNotEmpty(oldMatrixList)) {
boolean result = this.removeBatchByIds(oldMatrixList);
if (!result) {
throw new ServiceException("删除老方阵失败,数据库异常", HttpStatus.ERROR);
}
LambdaQueryWrapper<PgsProgressCategory> lqw = new LambdaQueryWrapper<>();
lqw.eq(PgsProgressCategory::getProjectId, projectId)
.in(PgsProgressCategory::getMatrixId, oldMatrixList.stream().map(FacMatrix::getId).toList());
List<PgsProgressCategory> progressCategories = progressCategoryService.list(lqw);
if (CollUtil.isNotEmpty(progressCategories)) {
boolean remove = progressCategoryService.remove(lqw);
if (!remove) {
throw new ServiceException("删除老方阵进度分类失败,数据库异常", HttpStatus.ERROR);
}
}
}
if (CollUtil.isNotEmpty(matrixList)) {
boolean result = this.saveBatch(matrixList);
if (!result) {
throw new ServiceException("批量新增方阵失败,数据库异常", HttpStatus.ERROR);
}
List<Long> matrixIdList = matrixList.stream().map(FacMatrix::getId).toList();
Boolean save = progressCategoryService.insertByTemplate(projectId, matrixIdList);
Boolean save = progressCategoryService.insertByTemplate(projectId, matrixList,oldMatrixList);
if (!save) {
throw new ServiceException("批量新增方阵进度分类失败,数据库异常", HttpStatus.ERROR);
}
}
if (CollUtil.isNotEmpty(oldMatrixList)) {
List<Long> oldMatrixIds = oldMatrixList.stream().map(FacMatrix::getId).toList();
boolean result = this.removeBatchByIds(oldMatrixIds);
if (!result) {
throw new ServiceException("删除老方阵失败,数据库异常", HttpStatus.ERROR);
}
}
return true;
}

View File

@ -77,8 +77,8 @@ public class FacPhotovoltaicPanelPartsServiceImpl implements IFacPhotovoltaicPan
@Resource
private ScheduledExecutorService scheduledExecutorService;
@Resource
@Lazy
@Resource
private FacPhotovoltaicPanelPartsServiceImpl self; // 注入自己
/**
@ -89,24 +89,25 @@ public class FacPhotovoltaicPanelPartsServiceImpl implements IFacPhotovoltaicPan
*/
@Override
public Boolean insertPartsByGeoJson(FacPhotovoltaicPanelPartsCreateByGeoJsonReq geoJson) {
// 设置 redis 防止多次操作
String operationRedisKey = FacRedisKeyConstant.getInOperationByProjectRedisKey(geoJson.getProjectId());
// Long projectId = geoJson.getProjectId();
Long projectId = 1930896467736707073L;
// 判断 redis key 是否存在,存在则返回
Object object = redisTemplate.opsForValue().get(operationRedisKey);
if (object != null && (Boolean) object) {
throw new ServiceException("项目下桩点、立柱、支架数据正在处理中,请勿重复操作", HttpStatus.BAD_REQUEST);
List<String> operationRedisKey = FacRedisKeyConstant.getInOperationRedisKeyList(projectId);
List<Object> list = redisTemplate.opsForValue().multiGet(operationRedisKey);
boolean hasValue = list != null && list.stream().anyMatch(Objects::nonNull);
if (hasValue) {
throw new ServiceException("项目下有设施数据正在处理中,请等待处理完毕后再操作", HttpStatus.BAD_REQUEST);
}
// 第一次接收请求,进行数据校验
int batchNum = geoJson.getBatchNum();
if (batchNum == 1) {
Long projectId = geoJson.getProjectId();
if (projectService.getById(projectId) == null) {
throw new ServiceException("项目不存在", HttpStatus.NOT_FOUND);
}
// 查询项目下光伏板
List<FacPhotovoltaicPanel> photovoltaicPanelList = photovoltaicPanelService.lambdaQuery()
.eq(FacPhotovoltaicPanel::getProjectId, projectId).list();
if (CollUtil.isEmpty(photovoltaicPanelList)) {
Long count = photovoltaicPanelService.lambdaQuery()
.eq(FacPhotovoltaicPanel::getProjectId, projectId).count();
if (count <= 0) {
throw new ServiceException("项目下无光伏板信息,请先创建光伏板信息后再添加桩点、立柱、支架信息", HttpStatus.NOT_FOUND);
}
}
@ -126,19 +127,22 @@ public class FacPhotovoltaicPanelPartsServiceImpl implements IFacPhotovoltaicPan
List<FacFeatureByPoint> allData = new ArrayList<>();
for (int i = 1; i <= totalBatch; i++) {
String batchKey = FacRedisKeyConstant.getBatchUploadPartsRedisKey(sessionId, i);
Object batch = redisTemplate.opsForValue().get(batchKey);
if (batch instanceof List<?>) {
allData.addAll((List<FacFeatureByPoint>) batch);
Object batchObj = redisTemplate.opsForValue().get(batchKey);
if (batchObj instanceof List<?>) {
@SuppressWarnings("unchecked")
List<FacFeatureByPoint> batch = (List<FacFeatureByPoint>) batchObj;
allData.addAll(batch);
}
}
// 设置 redis key防止多次操作
redisTemplate.opsForValue().set(operationRedisKey, true);
messageDto.setMessage("桩点、立柱、支架数据上传完毕,数据处理中");
String operationPartsRedisKey = FacRedisKeyConstant.getPartsInOperationByProjectRedisKey(projectId);
redisTemplate.opsForValue().set(operationPartsRedisKey, true);
messageDto.setMessage("桩点、立柱、支架数据上传完毕,正在处理中");
SseMessageUtils.publishMessage(messageDto);
scheduledExecutorService.execute(() -> {
try {
// 合并后的数据处理,如入库
this.saveBatch(geoJson.getProjectId(), allData, userId);
this.saveBatch(projectId, allData, userId);
} catch (Exception e) {
messageDto.setMessage("桩点、立柱、支架数据处理失败,请联系管理员处理");
SseMessageUtils.publishMessage(messageDto);
@ -150,7 +154,7 @@ public class FacPhotovoltaicPanelPartsServiceImpl implements IFacPhotovoltaicPan
String batchKey = FacRedisKeyConstant.getBatchUploadPartsRedisKey(sessionId, i);
redisTemplate.delete(batchKey);
}
redisTemplate.delete(operationRedisKey);
redisTemplate.delete(operationPartsRedisKey);
}
messageDto.setMessage("桩点、立柱、支架数据处理完毕");
SseMessageUtils.publishMessage(messageDto);
@ -625,7 +629,7 @@ public class FacPhotovoltaicPanelPartsServiceImpl implements IFacPhotovoltaicPan
});
long count = photovoltaicPanelPointService.count(pointWrapper);
if (count <= 0) {
throw new ServiceException("光伏板桩点数据不存在,请导入数据后再进行操作`", HttpStatus.NOT_FOUND);
throw new ServiceException("光伏板桩点数据不存在,请导入数据后再进行操作", HttpStatus.NOT_FOUND);
}
pointWrapper.set(FacPhotovoltaicPanelPoint::getFinishDate, finishDate);
pointWrapper.set(FacPhotovoltaicPanelPoint::getFinishType, FacFinishTypeEnum.HAND.getValue());

View File

@ -14,6 +14,8 @@ import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.common.sse.dto.SseMessageDto;
import org.dromara.common.sse.utils.SseMessageUtils;
import org.dromara.facility.constant.FacRedisKeyConstant;
import org.dromara.facility.domain.FacMatrix;
import org.dromara.facility.domain.FacPhotovoltaicPanel;
@ -36,7 +38,6 @@ import org.dromara.progress.domain.PgsProgressCategory;
import org.dromara.progress.service.IPgsProgressCategoryService;
import org.dromara.project.service.IBusProjectService;
import org.dromara.utils.JSTUtil;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.dao.DataAccessException;
@ -78,6 +79,13 @@ public class FacPhotovoltaicPanelServiceImpl extends ServiceImpl<FacPhotovoltaic
@Resource
private RedisTemplate<String, Object> redisTemplate;
@Resource
private ScheduledExecutorService scheduledExecutorService;
@Lazy
@Resource
private FacPhotovoltaicPanelServiceImpl self; // 注入自己
/**
* 查询设施-光伏板
*
@ -162,166 +170,232 @@ public class FacPhotovoltaicPanelServiceImpl extends ServiceImpl<FacPhotovoltaic
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean insertByGeoJson(FacPhotovoltaicPanelCreateByGeoJsonReq geoJson) {
// 判断当前项目是否正在执行桩点、立柱、支架数据
String operationRedisKey = FacRedisKeyConstant.getInOperationByProjectRedisKey(geoJson.getProjectId());
// Long projectId = geoJson.getProjectId();
Long projectId = 1930896467736707073L;
// 判断 redis key 是否存在,存在则返回
Object object = redisTemplate.opsForValue().get(operationRedisKey);
if (object != null && (Boolean) object) {
throw new ServiceException("项目下桩点、立柱、支架数据正在处理中,请等待处理完毕后操作", HttpStatus.BAD_REQUEST);
List<String> operationRedisKey = FacRedisKeyConstant.getInOperationRedisKeyList(projectId);
List<Object> list = redisTemplate.opsForValue().multiGet(operationRedisKey);
boolean hasValue = list != null && list.stream().anyMatch(Objects::nonNull);
if (hasValue) {
throw new ServiceException("项目下有设施数据正在处理中,请等待处理完毕后再操作", HttpStatus.BAD_REQUEST);
}
Long projectId = geoJson.getProjectId();
if (projectService.getById(projectId) == null) {
throw new ServiceException("项目不存在", HttpStatus.NOT_FOUND);
}
// 获取项目下方阵信息
List<FacMatrix> matrixList = matrixService.lambdaQuery()
.select(FacMatrix::getId, FacMatrix::getPositions)
.eq(FacMatrix::getProjectId, projectId).list();
if (CollUtil.isEmpty(matrixList)) {
throw new ServiceException("项目下无方阵数据,请先创建方阵信息后再添加光伏板信息", HttpStatus.NOT_FOUND);
}
// 获取当下项目下光伏板的信息
List<FacPhotovoltaicPanel> oldPhotovoltaicPanelList = this.lambdaQuery()
.eq(FacPhotovoltaicPanel::getProjectId, projectId).list();
Map<String, FacPhotovoltaicPanel> photovoltaicPanelMap = oldPhotovoltaicPanelList.stream()
.collect(Collectors.toMap(
panel -> panel.getName() + "_" + panel.getProgressCategoryId(),
Function.identity(),
(existing, replacement) -> existing // 如果有重复,保留第一个
));
List<FacGeoJsonByPlane> locationGeoJsonList = geoJson.getLocationGeoJson();
List<FacFeatureByPlane> locationFeatures = new ArrayList<>();
for (FacGeoJsonByPlane geoJsonByPlane : locationGeoJsonList) {
locationFeatures.addAll(geoJsonByPlane.getFeatures());
// 获取 redis key
String sessionId = geoJson.getSessionId();
int batchNum = geoJson.getBatchNum();
int totalBatch = geoJson.getTotalBatch();
// 获取所有光伏板位置信息
List<FacGeoJsonByPlane> locationGeoJsonBatchList = geoJson.getLocationGeoJson();
if (CollUtil.isNotEmpty(locationGeoJsonBatchList)) {
List<FacFeatureByPlane> locationFeaturesBatch = new ArrayList<>();
for (FacGeoJsonByPlane geoJsonByPlane : locationGeoJsonBatchList) {
locationFeaturesBatch.addAll(geoJsonByPlane.getFeatures());
}
// 存储到 Redis设置过期时间 30 分钟
String redisKeyByLocation = FacRedisKeyConstant.getBatchUploadPanelRedisKey(sessionId, batchNum, FacRedisKeyConstant.GEO_TYPE_LOCAL);
redisTemplate.opsForValue().set(redisKeyByLocation, locationFeaturesBatch, 1800, TimeUnit.SECONDS);
}
// 获取所有对应名称的点
List<FacGeoJsonByPoint> nameGeoJsonList = geoJson.getNameGeoJson();
List<FacFeatureByPoint> nameFeatures = new ArrayList<>();
for (FacGeoJsonByPoint geoJsonByPoint : nameGeoJsonList) {
nameFeatures.addAll(geoJsonByPoint.getFeatures());
}
// 获取进度类别信息
List<PgsProgressCategory> progressCategoryList = progressCategoryService.lambdaQuery()
.in(PgsProgressCategory::getWorkType, PgsProgressCategoryConstant.PHOTOVOLTAIC_PANEL_PROGRESS_CATEGORY_WORK_TYPE).list();
Map<Long, List<PgsProgressCategory>> progressCategoryMap = progressCategoryList.stream()
.collect(Collectors.groupingBy(PgsProgressCategory::getMatrixId));
List<FacPhotovoltaicPanel> allPanels = new ArrayList<>();
List<Future<List<FacPhotovoltaicPanel>>> futures = new ArrayList<>();
Long userId = LoginHelper.getUserId();
// 构建光伏板实体集合
try (ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors())) {
for (FacFeatureByPoint nameFeature : nameFeatures) {
Future<List<FacPhotovoltaicPanel>> future = executorService.submit(() -> {
List<FacPhotovoltaicPanel> panelList = new ArrayList<>();
// ① 找到该点对应的 polygon优先包含否则最近
FacFeatureByPlane matchedPolygon = JSTUtil.findNearestOrContainingPolygon(nameFeature, locationFeatures);
if (matchedPolygon == null) return Collections.emptyList();
// ② 获取 geometry 坐标
List<List<Double>> coordinates = matchedPolygon.getGeometry().getCoordinates().getFirst();
// ③ 判断所属方阵
FacMatrix matrix = matrixService.getMatrixIdBy2Coordinates(matrixList, coordinates);
if (matrix == null) return Collections.emptyList();
Long matrixId = matrix.getId();
// ④ 获取进度类别
List<PgsProgressCategory> progressCategoryListByMatrix = progressCategoryMap.get(matrixId);
if (CollUtil.isEmpty(progressCategoryListByMatrix)) return Collections.emptyList();
// ⑤ 获取名称
String name = nameFeature.getProperties() != null ? nameFeature.getProperties().getText() : null;
if (StringUtils.isBlank(name)) return Collections.emptyList();
// ⑥ 构建面板数据
for (PgsProgressCategory progressCategory : progressCategoryListByMatrix) {
FacPhotovoltaicPanel panel = new FacPhotovoltaicPanel();
panel.setMatrixId(matrixId);
panel.setName(name);
panel.setProjectId(projectId);
panel.setPositions(JSONUtil.toJsonStr(coordinates));
panel.setCreateBy(userId);
panel.setUpdateBy(userId);
String mapKey = name + "_" + progressCategory.getId();
FacPhotovoltaicPanel oldPanel = photovoltaicPanelMap.get(mapKey);
if (oldPanel != null) {
panel.setStatus(oldPanel.getStatus());
if (FacFinishStatusEnum.FINISH.getValue().equals(oldPanel.getStatus())) {
panel.setFinishType(oldPanel.getFinishType());
panel.setFinishDate(oldPanel.getFinishDate());
}
panel.setProgressCategoryId(oldPanel.getProgressCategoryId());
panel.setProgressCategoryName(oldPanel.getProgressCategoryName());
} else {
panel.setProgressCategoryId(progressCategory.getId());
panel.setProgressCategoryName(progressCategory.getName());
}
panelList.add(panel);
}
return panelList;
});
futures.add(future);
List<FacGeoJsonByPoint> nameGeoJsonBatchList = geoJson.getNameGeoJson();
if (CollUtil.isNotEmpty(nameGeoJsonBatchList)) {
List<FacFeatureByPoint> nameFeaturesBatch = new ArrayList<>();
for (FacGeoJsonByPoint geoJsonByPoint : nameGeoJsonBatchList) {
nameFeaturesBatch.addAll(geoJsonByPoint.getFeatures());
}
// 等待所有结果
for (Future<List<FacPhotovoltaicPanel>> future : futures) {
try {
allPanels.addAll(future.get());
} catch (Exception e) {
log.error("线程执行异常", e);
// 存储到 Redis设置过期时间 30 分钟
String redisKeyByName = FacRedisKeyConstant.getBatchUploadPanelRedisKey(sessionId, batchNum, FacRedisKeyConstant.GEO_TYPE_NAME);
redisTemplate.opsForValue().set(redisKeyByName, nameFeaturesBatch, 1800, TimeUnit.SECONDS);
}
log.info("已接收第 {} 批数据,共 {} 批", batchNum, totalBatch);
Long userId = LoginHelper.getUserId();
SseMessageDto messageDto = new SseMessageDto();
messageDto.setUserIds(List.of(userId));
// 如果是最后一批,开始合并
if (batchNum == totalBatch) {
List<FacFeatureByPlane> locationFeatures = new ArrayList<>();
List<FacFeatureByPoint> nameFeatures = new ArrayList<>();
for (int i = 1; i <= totalBatch; i++) {
String batchKeyByLocation = FacRedisKeyConstant.getBatchUploadPanelRedisKey(sessionId, i, FacRedisKeyConstant.GEO_TYPE_LOCAL);
String batchKeyByName = FacRedisKeyConstant.getBatchUploadPanelRedisKey(sessionId, i, FacRedisKeyConstant.GEO_TYPE_NAME);
Object batchLocationObj = redisTemplate.opsForValue().get(batchKeyByLocation);
Object batchNameObj = redisTemplate.opsForValue().get(batchKeyByName);
if (batchLocationObj instanceof List<?>) {
@SuppressWarnings("unchecked")
List<FacFeatureByPlane> batch = (List<FacFeatureByPlane>) batchLocationObj;
locationFeatures.addAll(batch);
}
if (batchNameObj instanceof List<?>) {
@SuppressWarnings("unchecked")
List<FacFeatureByPoint> batch = (List<FacFeatureByPoint>) batchNameObj;
nameFeatures.addAll(batch);
}
}
}
// 自定义线程池IO 密集型线程池)
ThreadPoolExecutor customExecutor = new ThreadPoolExecutor(
20, // 核心线程数
50, // 最大线程数
60L, // 线程空闲存活时间
TimeUnit.SECONDS, // 存活时间单位
new LinkedBlockingQueue<>(10000), // 阻塞队列容量
new ThreadPoolExecutor.CallerRunsPolicy() // 拒绝策略:由调用线程处理任务
);
// 分批处理,避免长事务,每次处理 1000 条数据
int batchSize = 1000;
// 保存所有批次任务
List<CompletableFuture<Void>> deleteFutures = new ArrayList<>();
int deleteSize = oldPhotovoltaicPanelList.size();
for (int i = 0; i < deleteSize; i += batchSize) {
int endIndex = Math.min(i + batchSize, deleteSize);
List<FacPhotovoltaicPanel> batchList = oldPhotovoltaicPanelList.subList(i, endIndex);
// 使用事务处理每批数据
// 获取代理
FacPhotovoltaicPanelServiceImpl photovoltaicPanelService = (FacPhotovoltaicPanelServiceImpl) AopContext.currentProxy();
// 异步处理每批数据,将任务添加到异步任务列表
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> photovoltaicPanelService.deleteBatchInner(batchList), customExecutor);
deleteFutures.add(future);
}
// 等待所有批次完成操作
CompletableFuture.allOf(deleteFutures.toArray(new CompletableFuture[0])).join();
// 保存所有批次任务
List<CompletableFuture<Void>> insertFutures = new ArrayList<>();
int totalSize = allPanels.size();
for (int i = 0; i < totalSize; i += batchSize) {
int endIndex = Math.min(i + batchSize, totalSize);
List<FacPhotovoltaicPanel> batchList = allPanels.subList(i, endIndex);
// 使用事务处理每批数据
// 获取代理
FacPhotovoltaicPanelServiceImpl photovoltaicPanelService = (FacPhotovoltaicPanelServiceImpl) AopContext.currentProxy();
// 异步处理每批数据,将任务添加到异步任务列表
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> photovoltaicPanelService.insertBatchInner(batchList), customExecutor);
insertFutures.add(future);
}
// 等待所有批次完成操作
CompletableFuture.allOf(insertFutures.toArray(new CompletableFuture[0])).join();
// 关闭线程池
customExecutor.shutdown();
// 更新数量
Map<Long, List<FacPhotovoltaicPanel>> countMap = allPanels
.stream().collect(Collectors.groupingBy(FacPhotovoltaicPanel::getProgressCategoryId));
for (PgsProgressCategory progressCategory : progressCategoryList) {
Long progressCategoryId = progressCategory.getId();
int total = 0;
if (countMap.containsKey(progressCategoryId)) {
total = countMap.get(progressCategoryId).size();
}
progressCategory.setTotal(BigDecimal.valueOf(total));
}
boolean result = progressCategoryService.updateBatchById(progressCategoryList);
if (!result) {
throw new ServiceException("更新进度类别失败,数据库异常", HttpStatus.ERROR);
// 设置 redis key防止多次操作
String operationPanelRedisKey = FacRedisKeyConstant.getPanelInOperationByProjectRedisKey(projectId);
redisTemplate.opsForValue().set(operationPanelRedisKey, true);
messageDto.setMessage("光伏板数据上传完毕,正在处理中");
SseMessageUtils.publishMessage(messageDto);
scheduledExecutorService.execute(() -> {
try {
// 获取当下项目下光伏板的信息
List<FacPhotovoltaicPanel> oldPhotovoltaicPanelList = this.lambdaQuery()
.eq(FacPhotovoltaicPanel::getProjectId, projectId).list();
Map<String, FacPhotovoltaicPanel> photovoltaicPanelMap = oldPhotovoltaicPanelList.stream()
.collect(Collectors.toMap(
panel -> panel.getName() + "_" + panel.getProgressCategoryId(),
Function.identity(),
(existing, replacement) -> existing // 如果有重复,保留第一个
));
// 获取进度类别信息
List<PgsProgressCategory> progressCategoryList = progressCategoryService.lambdaQuery()
.in(PgsProgressCategory::getWorkType, PgsProgressCategoryConstant.PHOTOVOLTAIC_PANEL_PROGRESS_CATEGORY_WORK_TYPE).list();
Map<Long, List<PgsProgressCategory>> progressCategoryMap = progressCategoryList.stream()
.collect(Collectors.groupingBy(PgsProgressCategory::getMatrixId));
List<FacPhotovoltaicPanel> allPanels = new ArrayList<>();
List<Future<List<FacPhotovoltaicPanel>>> futures = new ArrayList<>();
// 构建光伏板实体集合
try (ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors())) {
for (FacFeatureByPoint nameFeature : nameFeatures) {
Future<List<FacPhotovoltaicPanel>> future = executorService.submit(() -> {
List<FacPhotovoltaicPanel> panelList = new ArrayList<>();
// ① 找到该点对应的 polygon优先包含否则最近
FacFeatureByPlane matchedPolygon = JSTUtil.findNearestOrContainingPolygon(nameFeature, locationFeatures);
if (matchedPolygon == null) return Collections.emptyList();
// ② 获取 geometry 坐标
List<List<Double>> coordinates = matchedPolygon.getGeometry().getCoordinates().getFirst();
// ③ 判断所属方阵
FacMatrix matrix = matrixService.getMatrixIdBy2Coordinates(matrixList, coordinates);
if (matrix == null) return Collections.emptyList();
Long matrixId = matrix.getId();
// ④ 获取进度类别
List<PgsProgressCategory> progressCategoryListByMatrix = progressCategoryMap.get(matrixId);
if (CollUtil.isEmpty(progressCategoryListByMatrix)) return Collections.emptyList();
// ⑤ 获取名称
String name = nameFeature.getProperties() != null ? nameFeature.getProperties().getText() : null;
if (StringUtils.isBlank(name)) return Collections.emptyList();
// ⑥ 构建面板数据
for (PgsProgressCategory progressCategory : progressCategoryListByMatrix) {
FacPhotovoltaicPanel panel = new FacPhotovoltaicPanel();
panel.setMatrixId(matrixId);
panel.setName(name);
panel.setProjectId(projectId);
panel.setPositions(JSONUtil.toJsonStr(coordinates));
panel.setCreateBy(userId);
panel.setUpdateBy(userId);
String mapKey = name + "_" + progressCategory.getId();
FacPhotovoltaicPanel oldPanel = photovoltaicPanelMap.get(mapKey);
if (oldPanel != null) {
panel.setStatus(oldPanel.getStatus());
if (FacFinishStatusEnum.FINISH.getValue().equals(oldPanel.getStatus())) {
panel.setFinishType(oldPanel.getFinishType());
panel.setFinishDate(oldPanel.getFinishDate());
}
panel.setProgressCategoryId(oldPanel.getProgressCategoryId());
panel.setProgressCategoryName(oldPanel.getProgressCategoryName());
} else {
panel.setProgressCategoryId(progressCategory.getId());
panel.setProgressCategoryName(progressCategory.getName());
}
panelList.add(panel);
}
return panelList;
});
futures.add(future);
}
// 等待所有结果
for (Future<List<FacPhotovoltaicPanel>> future : futures) {
try {
allPanels.addAll(future.get());
} catch (Exception e) {
log.error("线程执行异常", e);
}
}
}
// 自定义线程池IO 密集型线程池)
ThreadPoolExecutor customExecutor = new ThreadPoolExecutor(
20, // 核心线程数
50, // 最大线程数
60L, // 线程空闲存活时间
TimeUnit.SECONDS, // 存活时间单位
new LinkedBlockingQueue<>(10000), // 阻塞队列容量
new ThreadPoolExecutor.CallerRunsPolicy() // 拒绝策略:由调用线程处理任务
);
// 分批处理,避免长事务,每次处理 1000 条数据
int batchSize = 1000;
// 保存所有批次任务
List<CompletableFuture<Void>> deleteFutures = new ArrayList<>();
int deleteSize = oldPhotovoltaicPanelList.size();
for (int i = 0; i < deleteSize; i += batchSize) {
int endIndex = Math.min(i + batchSize, deleteSize);
List<FacPhotovoltaicPanel> batchList = oldPhotovoltaicPanelList.subList(i, endIndex);
// 使用事务处理每批数据
// 获取代理
FacPhotovoltaicPanelServiceImpl photovoltaicPanelService = self;
// 异步处理每批数据,将任务添加到异步任务列表
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> photovoltaicPanelService.deleteBatchInner(batchList), customExecutor);
deleteFutures.add(future);
}
// 等待所有批次完成操作
CompletableFuture.allOf(deleteFutures.toArray(new CompletableFuture[0])).join();
// 保存所有批次任务
List<CompletableFuture<Void>> insertFutures = new ArrayList<>();
int totalSize = allPanels.size();
for (int i = 0; i < totalSize; i += batchSize) {
int endIndex = Math.min(i + batchSize, totalSize);
List<FacPhotovoltaicPanel> batchList = allPanels.subList(i, endIndex);
// 使用事务处理每批数据
// 获取代理
FacPhotovoltaicPanelServiceImpl photovoltaicPanelService = self;
// 异步处理每批数据,将任务添加到异步任务列表
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> photovoltaicPanelService.insertBatchInner(batchList), customExecutor);
insertFutures.add(future);
}
// 等待所有批次完成操作
CompletableFuture.allOf(insertFutures.toArray(new CompletableFuture[0])).join();
// 关闭线程池
customExecutor.shutdown();
// 更新数量
Map<Long, List<FacPhotovoltaicPanel>> countMap = allPanels
.stream().collect(Collectors.groupingBy(FacPhotovoltaicPanel::getProgressCategoryId));
for (PgsProgressCategory progressCategory : progressCategoryList) {
Long progressCategoryId = progressCategory.getId();
int total = 0;
if (countMap.containsKey(progressCategoryId)) {
total = countMap.get(progressCategoryId).size();
}
progressCategory.setTotal(BigDecimal.valueOf(total));
}
boolean result = progressCategoryService.updateBatchById(progressCategoryList);
if (!result) {
throw new ServiceException("更新进度类别失败,数据库异常", HttpStatus.ERROR);
}
messageDto.setMessage("光伏板数据处理完毕");
SseMessageUtils.publishMessage(messageDto);
} catch (Exception e) {
messageDto.setMessage("光伏板数据处理失败,请联系管理员处理");
SseMessageUtils.publishMessage(messageDto);
log.error("光伏板数据处理失败", e);
throw new ServiceException("光伏板数据处理失败", HttpStatus.ERROR);
} finally {
// 清理缓存
for (int i = 1; i <= totalBatch; i++) {
String batchKeyByLocation = FacRedisKeyConstant.getBatchUploadPanelRedisKey(sessionId, i, FacRedisKeyConstant.GEO_TYPE_LOCAL);
String batchKeyByName = FacRedisKeyConstant.getBatchUploadPanelRedisKey(sessionId, i, FacRedisKeyConstant.GEO_TYPE_NAME);
redisTemplate.delete(batchKeyByLocation);
redisTemplate.delete(batchKeyByName);
}
redisTemplate.delete(operationPanelRedisKey);
}
});
}
return true;
}

View File

@ -0,0 +1,38 @@
package org.dromara.job.once;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.dromara.manager.ys7manager.Ys7Manager;
import org.dromara.manager.ys7manager.vo.Ys7QueryDeviceResponseVo;
import org.dromara.other.service.IOthYs7DeviceService;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* @author lcj
* @date 2025/6/13 11:08
*/
@Slf4j
//@Component
public class FullSyncYs7DeviceData implements CommandLineRunner {
@Resource
private Ys7Manager ys7Manager;
@Resource
private IOthYs7DeviceService ys7DeviceService;
@Override
public void run(String... args) throws Exception {
log.info("开始同步摄像头设备数据");
List<Ys7QueryDeviceResponseVo> ys7QueryDeviceList = ys7Manager.queryAllDeviceList();
Boolean result = ys7DeviceService.saveOrUpdateByDeviceList(ys7QueryDeviceList);
if (result) {
log.info("摄像头设备数据同步成功");
} else {
log.info("没有需要同步的设备");
}
}
}

View File

@ -0,0 +1,33 @@
package org.dromara.manager.ys7manager;
/**
* @author lcj
* @date 2025/6/12 16:56
*/
public interface Ys7Constant {
/**
* token redis 缓存 key 前缀
*/
String TOKEN_REDIS_KEY = "ys7:token";
/**
* 分页查询设备列表最大条数
*/
Integer MAX_PAGE_SIZE = 50;
/**
* 获取 token 请求地址 Post
*/
String getTokenUrlByPost = "https://open.ys7.com/api/lapp/token/get";
/**
* 分页查询设备列表请求地址 Post
*/
String queryDevicePageUrlByPost = "https://open.ys7.com/api/lapp/device/list";
/**
* 修改设备名称请求地址 Post
*/
String updateDeviceNameUrlByPost = "https://open.ys7.com/api/lapp/device/name/update";
}

View File

@ -0,0 +1,68 @@
package org.dromara.manager.ys7manager;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.dromara.manager.ys7manager.vo.Ys7QueryDeviceResponseVo;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
* @author lcj
* @date 2025/6/13 11:10
*/
@Slf4j
@Component
public class Ys7Manager {
@Resource
private Ys7Properties ys7Properties;
@Resource
private StringRedisTemplate stringRedisTemplate;
/**
* 获取所有设备列表
*
* @return 设备列表
*/
public List<Ys7QueryDeviceResponseVo> queryAllDeviceList() {
String token = getToken();
int pageStart = 0;
int pageSize = 50;
List<Ys7QueryDeviceResponseVo> deviceList = new ArrayList<>();
while (true) {
// 分页获取设备
List<Ys7QueryDeviceResponseVo> list = Ys7RequestUtils.queryDeviceVoList(token, pageStart, pageSize);
deviceList.addAll(list);
// 获取设备数量小于分页大小,则结束循环
if (list.size() < pageSize) {
break;
}
pageStart++;
}
return deviceList;
}
/**
* 获取 token
*
* @return token
*/
public String getToken() {
String tokenRedisKey = Ys7Constant.TOKEN_REDIS_KEY;
String token = stringRedisTemplate.opsForValue().get(tokenRedisKey);
// 不为空,直接返回 token
if (token != null) {
return token;
}
// 向云服务商请求新的 token
String newToken = Ys7RequestUtils.getToken(ys7Properties.getAppKey(), ys7Properties.getAppSecret());
// 设置有效期
stringRedisTemplate.opsForValue().set(tokenRedisKey, newToken, 6, TimeUnit.DAYS);
return newToken;
}
}

View File

@ -0,0 +1,26 @@
package org.dromara.manager.ys7manager;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
/**
* @author lcj
* @date 2025/6/12 16:50
*/
@Data
@Configuration
@ConfigurationProperties(prefix = "ys7")
public class Ys7Properties {
/**
* appKey
*/
private String appKey;
/**
* appSecret
*/
private String appSecret;
}

View File

@ -0,0 +1,141 @@
package org.dromara.manager.ys7manager;
import cn.hutool.core.lang.Validator;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.constant.HttpStatus;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.manager.ys7manager.vo.Ys7NoDataResponseVo;
import org.dromara.manager.ys7manager.vo.Ys7PageResponseVo;
import org.dromara.manager.ys7manager.vo.Ys7QueryDeviceResponseVo;
import org.dromara.manager.ys7manager.vo.Ys7ResponseVo;
import java.util.HashMap;
import java.util.List;
/**
* @author lcj
* @date 2025/6/12 16:54
*/
@Slf4j
public class Ys7RequestUtils {
/**
* 获取 token
*
* @param appKey appKey
* @param appSecret appSecret
* @return token
*/
public static String getToken(String appKey, String appSecret) {
HashMap<String, Object> paramMap = new HashMap<>();
paramMap.put("appKey", appKey);
paramMap.put("appSecret", appSecret);
String errorMsg = "Ys7 Token 请求失败";
try (HttpResponse response = HttpRequest.post(Ys7Constant.getTokenUrlByPost)
.form(paramMap)
.execute()) {
if (!response.isOk()) {
log.error("{}{}", errorMsg, response.getStatus());
throw new ServiceException(errorMsg + response.getStatus());
}
String body = response.body();
Ys7ResponseVo responseVo = JSONUtil.toBean(body, Ys7ResponseVo.class);
if (!responseVo.getCode().equals("200")) {
log.error("{}{}", errorMsg, responseVo.getMsg());
throw new ServiceException(errorMsg + responseVo.getMsg());
}
log.info("Ys7 Token 请求成功:{}", body);
String data = responseVo.getData();
JSONObject jsonObject = JSONUtil.parseObj(data);
return jsonObject.get("accessToken", String.class);
}
}
/**
* 查询设备列表
*
* @param accessToken 萤石开放API访问令牌
* @param pageStart 分页页码起始页从0开始不超过400页
* @param pageSize 分页大小默认为10不超过50
* @return 设备列表
*/
public static List<Ys7QueryDeviceResponseVo> queryDeviceVoList(String accessToken, Integer pageStart, Integer pageSize) {
if (pageStart < 0 || pageStart > 400) {
throw new ServiceException("分页页码超出范围");
}
if (pageSize < 0 || pageSize > 50) {
pageSize = Ys7Constant.MAX_PAGE_SIZE;
}
HashMap<String, Object> paramMap = new HashMap<>();
paramMap.put("accessToken", accessToken);
paramMap.put("pageStart", pageStart);
paramMap.put("pageSize", pageSize);
String errorMsg = String.format("Ys7 分页查询设备列表 第%s页大小%s 请求失败", (pageStart + 1), pageSize);
try (HttpResponse response = HttpRequest.post(Ys7Constant.queryDevicePageUrlByPost)
.form(paramMap)
.execute()) {
if (!response.isOk()) {
log.error("{}{}", errorMsg, response.getStatus());
throw new ServiceException(errorMsg + response.getStatus());
}
String body = response.body();
Ys7PageResponseVo responseVo = JSONUtil.toBean(body, Ys7PageResponseVo.class);
if (!responseVo.getCode().equals("200")) {
log.error("{}{}", errorMsg, responseVo.getMsg());
throw new ServiceException(errorMsg + responseVo.getMsg());
}
log.info("Ys7 分页查询设备列表 第{}页大小{} 请求成功:{}", (pageStart + 1), pageSize, body);
return JSONUtil.toList(responseVo.getData(), Ys7QueryDeviceResponseVo.class);
}
}
/**
* 修改设备名称
*
* @param accessToken accessToken
* @param deviceSerial 设备序列号
* @param deviceName 设备名称长度不大于50字节不能包含特殊字符
* @return 是否修改成功
*/
public static Boolean updateDeviceName(String accessToken, String deviceSerial, String deviceName) {
// 参数校验
if (StringUtils.isAnyBlank(accessToken, deviceSerial, deviceName)) {
throw new ServiceException("修改设备名称参数为空", HttpStatus.BAD_REQUEST);
}
if (deviceName.length() > 50) {
throw new ServiceException("设备名称长度不能超过50个字符", HttpStatus.BAD_REQUEST);
}
if (!Validator.isGeneralWithChinese(deviceName)) {
throw new ServiceException("设备名称不能包含特殊字符", HttpStatus.BAD_REQUEST);
}
// 组合请求体
HashMap<String, Object> paramMap = new HashMap<>();
paramMap.put("accessToken", accessToken);
paramMap.put("deviceSerial", deviceSerial);
paramMap.put("deviceName", deviceName);
// 发送请求
String errorMsg = "修改设备名称请求失败";
try (HttpResponse response = HttpRequest.post(Ys7Constant.updateDeviceNameUrlByPost)
.form(paramMap)
.execute()) {
if (!response.isOk()) {
log.error("{}{}", errorMsg, response.getStatus());
throw new ServiceException(errorMsg + response.getStatus());
}
String body = response.body();
Ys7NoDataResponseVo responseVo = JSONUtil.toBean(body, Ys7NoDataResponseVo.class);
if (!responseVo.getCode().equals("200")) {
log.error("{}{}", errorMsg, responseVo.getMsg());
throw new ServiceException(errorMsg + responseVo.getMsg());
}
log.info("修改设备名称请求成功,设备 {} 名称修改为 {}", deviceSerial, deviceName);
return true;
}
}
}

View File

@ -0,0 +1,22 @@
package org.dromara.manager.ys7manager.vo;
import lombok.Data;
/**
* @author lcj
* @date 2025/6/13 14:30
*/
@Data
public class Ys7NoDataResponseVo {
/**
* 响应码
*/
private String code;
/**
* 响应信息
*/
private String msg;
}

View File

@ -0,0 +1,32 @@
package org.dromara.manager.ys7manager.vo;
import lombok.Data;
/**
* @author lcj
* @date 2025/6/12 17:35
*/
@Data
public class Ys7PageResponseVo {
/**
* 响应码
*/
private String code;
/**
* 响应数据
*/
private String data;
/**
* 响应信息
*/
private String msg;
/**
* 分页信息
*/
private String page;
}

View File

@ -0,0 +1,72 @@
package org.dromara.manager.ys7manager.vo;
import lombok.Data;
/**
* @author lcj
* @date 2025/6/12 17:33
*/
@Data
public class Ys7QueryDeviceResponseVo {
/**
* 条目索引
*/
private String id;
/**
* 设备序列号
*/
private String deviceSerial;
/**
* 设备名称
*/
private String deviceName;
/**
* 设备型号
*/
private String deviceType;
/**
* 设备在线状态1-在线0-离线
*/
private Integer status;
/**
* 布撤防状态
*/
private Integer defence;
/**
* 固件版本号
*/
private String deviceVersion;
/**
* 用户添加时间
*/
private Long addTime;
/**
* 设备最后更新时间
*/
private Long updateTime;
/**
* 设备二级类目名称
*/
private String parentCategory;
/**
* 设备风险安全等级0-安全大于0有风险风险越高值越大
*/
private Integer riskLevel;
/**
* 设备IP地址
*/
private String netAddress;
}

View File

@ -0,0 +1,27 @@
package org.dromara.manager.ys7manager.vo;
import lombok.Data;
/**
* @author lcj
* @date 2025/6/12 17:14
*/
@Data
public class Ys7ResponseVo {
/**
* 响应码
*/
private String code;
/**
* 响应数据
*/
private String data;
/**
* 响应信息
*/
private String msg;
}

View File

@ -0,0 +1,108 @@
package org.dromara.other.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.web.core.BaseController;
import org.dromara.other.domain.dto.devicepreset.OthDevicePresetCreateReq;
import org.dromara.other.domain.dto.devicepreset.OthDevicePresetQueryReq;
import org.dromara.other.domain.dto.devicepreset.OthDevicePresetUpdateReq;
import org.dromara.other.domain.vo.devicepreset.OthDevicePresetVo;
import org.dromara.other.service.IOthDevicePresetService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 摄像头预置位
*
* @author lcj
* @date 2025-06-13
*/
@Validated
@RestController
@RequestMapping("/other/devicePreset")
public class OthDevicePresetController extends BaseController {
@Resource
private IOthDevicePresetService othDevicePresetService;
/**
* 查询摄像头预置位列表
*/
@SaCheckPermission("other:devicePreset:list")
@GetMapping("/list")
public TableDataInfo<OthDevicePresetVo> list(OthDevicePresetQueryReq req, PageQuery pageQuery) {
return othDevicePresetService.queryPageList(req, pageQuery);
}
/**
* 导出摄像头预置位列表
*/
@SaCheckPermission("other:devicePreset:export")
@Log(title = "摄像头预置位", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(OthDevicePresetQueryReq req, HttpServletResponse response) {
List<OthDevicePresetVo> list = othDevicePresetService.queryList(req);
ExcelUtil.exportExcel(list, "摄像头预置位", OthDevicePresetVo.class, response);
}
/**
* 获取摄像头预置位详细信息
*
* @param id 主键
*/
@SaCheckPermission("other:devicePreset:query")
@GetMapping("/{id}")
public R<OthDevicePresetVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long id) {
return R.ok(othDevicePresetService.queryById(id));
}
/**
* 新增摄像头预置位
*/
@SaCheckPermission("other:devicePreset:add")
@Log(title = "摄像头预置位", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Long> add(@Validated(AddGroup.class) @RequestBody OthDevicePresetCreateReq req) {
return R.ok(othDevicePresetService.insertByBo(req));
}
/**
* 修改摄像头预置位
*/
@SaCheckPermission("other:devicePreset:edit")
@Log(title = "摄像头预置位", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody OthDevicePresetUpdateReq req) {
return toAjax(othDevicePresetService.updateByBo(req));
}
/**
* 删除摄像头预置位
*
* @param ids 主键串
*/
@SaCheckPermission("other:devicePreset:remove")
@Log(title = "摄像头预置位", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] ids) {
return toAjax(othDevicePresetService.deleteWithValidByIds(List.of(ids), true));
}
}

View File

@ -0,0 +1,132 @@
package org.dromara.other.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.web.core.BaseController;
import org.dromara.manager.ys7manager.Ys7Manager;
import org.dromara.other.domain.dto.ys7device.OthYs7DeviceQueryReq;
import org.dromara.other.domain.dto.ys7device.OthYs7DeviceUpdateEncryptedReq;
import org.dromara.other.domain.dto.ys7device.OthYs7DeviceUpdateReq;
import org.dromara.other.domain.dto.ys7device.OthYs7DeviceWithProjectReq;
import org.dromara.other.domain.vo.ys7device.OthYs7DeviceVo;
import org.dromara.other.service.IOthYs7DeviceService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 萤石摄像头
*
* @author lcj
* @date 2025-06-13
*/
@Validated
@RestController
@RequestMapping("/other/ys7Device")
public class OthYs7DeviceController extends BaseController {
@Resource
private IOthYs7DeviceService othYs7DeviceService;
@Resource
private Ys7Manager ys7Manager;
/**
* 查询萤石摄像头列表
*/
@SaCheckPermission("other:ys7Device:list")
@GetMapping("/list")
public TableDataInfo<OthYs7DeviceVo> list(OthYs7DeviceQueryReq req, PageQuery pageQuery) {
return othYs7DeviceService.queryPageList(req, pageQuery);
}
/**
* 导出萤石摄像头列表
*/
@SaCheckPermission("other:ys7Device:export")
@Log(title = "萤石摄像头", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(OthYs7DeviceQueryReq req, HttpServletResponse response) {
List<OthYs7DeviceVo> list = othYs7DeviceService.queryList(req);
ExcelUtil.exportExcel(list, "萤石摄像头", OthYs7DeviceVo.class, response);
}
/**
* 获取萤石摄像头详细信息
*
* @param id 主键
*/
@SaCheckPermission("other:ys7Device:query")
@GetMapping("/{id}")
public R<OthYs7DeviceVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long id) {
return R.ok(othYs7DeviceService.queryById(id));
}
/**
* 修改萤石摄像头
*/
@SaCheckPermission("other:ys7Device:edit")
@Log(title = "萤石摄像头", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody OthYs7DeviceUpdateReq req) {
return toAjax(othYs7DeviceService.updateByBo(req));
}
/**
* 修改萤石摄像头所属项目
*/
@SaCheckPermission("other:ys7Device:edit")
@Log(title = "萤石摄像头", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping("/with/project")
public R<Void> updateWithProject(@Validated @RequestBody OthYs7DeviceWithProjectReq req) {
return toAjax(othYs7DeviceService.updateWithProject(req));
}
/**
* 修改萤石摄像头视频加密
*/
@SaCheckPermission("other:ys7Device:edit")
@Log(title = "萤石摄像头", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping("/video/encrypted")
public R<Void> updateVideoEncrypted(@Validated @RequestBody OthYs7DeviceUpdateEncryptedReq req) {
return toAjax(othYs7DeviceService.updateVideoEncrypted(req));
}
/**
* 删除萤石摄像头
*
* @param ids 主键串
*/
@SaCheckPermission("other:ys7Device:remove")
@Log(title = "萤石摄像头", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] ids) {
return toAjax(othYs7DeviceService.deleteWithValidByIds(List.of(ids), true));
}
/**
* 获取 token
*/
@SaCheckPermission("other:ys7Device:query")
@GetMapping("/get/token")
public R<String> getToken() {
return R.ok(ys7Manager.getToken());
}
}

View File

@ -0,0 +1,60 @@
package org.dromara.other.domain;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
* 摄像头预置位对象 oth_device_preset
*
* @author lcj
* @date 2025-06-13
*/
@Data
@TableName("oth_device_preset")
public class OthDevicePreset implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键id
*/
@TableId(value = "id")
private Long id;
/**
* 设备序列号
*/
private String deviceSerial;
/**
* 通道号
*/
private Long channelNo;
/**
* 预置点序号
*/
private Long index;
/**
* 预置点
*/
private String name;
/**
* 创建时间
*/
private Date createTime;
/**
* 更新时间
*/
private Date updateTime;
}

View File

@ -0,0 +1,117 @@
package org.dromara.other.domain;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
* 萤石摄像头对象 oth_ys7_device
*
* @author lcj
* @date 2025-06-13
*/
@Data
@TableName("oth_ys7_device")
public class OthYs7Device implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键id
*/
@TableId(value = "id")
private Long id;
/**
* 项目id
*/
private Long projectId;
/**
* 设备序列号
*/
private String deviceSerial;
/**
* 设备名称
*/
private String deviceName;
/**
* 设备型号
*/
private String deviceType;
/**
* 设备在线状态(0离线 1在线)
*/
private Integer status;
/**
* 布撤防状态
*/
private Long defence;
/**
* 固件版本号
*/
private String deviceVersion;
/**
* 摄像头坐标信息
*/
private String position;
/**
* 设备添加时间
*/
private Date deviceCreateTime;
/**
* 设备最后更新时间
*/
private Date deviceUpdateTime;
/**
* 设备风险安全等级(0安全 大于0值越大风险越高)
*/
private Integer riskLevel;
/**
* 视频加密(0关闭 1开启)
*/
private Integer videoEncrypted;
/**
* 备注
*/
private String remark;
/**
* 创建时间
*/
private Date createTime;
/**
* 更新时间
*/
private Date updateTime;
/**
* 删除时间
*/
private Date deletedAt;
/**
* 是否删除0正常 1删除
*/
@TableLogic
private Integer isDelete;
}

View File

@ -0,0 +1,40 @@
package org.dromara.other.domain.dto.devicepreset;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* @author lcj
* @date 2025/6/13 17:16
*/
@Data
public class OthDevicePresetCreateReq implements Serializable {
@Serial
private static final long serialVersionUID = -6326735809456235573L;
/**
* 设备序列号
*/
@NotNull(message = "设备序列号不能为空")
private String deviceSerial;
/**
* 通道号
*/
private Long channelNo;
/**
* 预置点序号
*/
private Long index;
/**
* 预置点
*/
private String name;
}

View File

@ -0,0 +1,40 @@
package org.dromara.other.domain.dto.devicepreset;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* @author lcj
* @date 2025/6/13 17:17
*/
@Data
public class OthDevicePresetQueryReq implements Serializable {
@Serial
private static final long serialVersionUID = 440026959610596318L;
/**
* 设备序列号
*/
@NotNull(message = "设备序列号不能为空")
private String deviceSerial;
/**
* 通道号
*/
private Long channelNo;
/**
* 预置点序号
*/
private Long index;
/**
* 预置点
*/
private String name;
}

View File

@ -0,0 +1,40 @@
package org.dromara.other.domain.dto.devicepreset;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* @author lcj
* @date 2025/6/13 17:17
*/
@Data
public class OthDevicePresetUpdateReq implements Serializable {
@Serial
private static final long serialVersionUID = -5204788392612423553L;
/**
* 主键id
*/
@NotNull(message = "主键id不能为空")
private Long id;
/**
* 通道号
*/
private Long channelNo;
/**
* 预置点序号
*/
private Long index;
/**
* 预置点
*/
private String name;
}

View File

@ -0,0 +1,48 @@
package org.dromara.other.domain.dto.ys7device;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* @author lcj
* @date 2025/6/13 10:19
*/
@Data
public class OthYs7DeviceQueryReq implements Serializable {
@Serial
private static final long serialVersionUID = -4341677730149529815L;
/**
* 设备序列号
*/
private String deviceSerial;
/**
* 项目id
*/
private Long projectId;
/**
* 设备名称
*/
private String deviceName;
/**
* 设备型号
*/
private String deviceType;
/**
* 固件版本号
*/
private String deviceVersion;
/**
* 设备在线状态(0离线 1在线)
*/
private Long status;
}

View File

@ -0,0 +1,28 @@
package org.dromara.other.domain.dto.ys7device;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* @author lcj
* @date 2025/6/13 16:20
*/
@Data
public class OthYs7DeviceUpdateEncryptedReq implements Serializable {
@Serial
private static final long serialVersionUID = -5570966854443595312L;
/**
* 主键
*/
private Long id;
/**
* 视频加密(0关闭 1开启)
*/
private Integer videoEncrypted;
}

View File

@ -0,0 +1,48 @@
package org.dromara.other.domain.dto.ys7device;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* @author lcj
* @date 2025/6/13 10:19
*/
@Data
public class OthYs7DeviceUpdateReq implements Serializable {
@Serial
private static final long serialVersionUID = -3434796275594146484L;
/**
* 主键id
*/
private Long id;
/**
* 项目id
*/
private Long projectId;
/**
* 设备名称
*/
private String deviceName;
/**
* 设备型号
*/
private String deviceType;
/**
* 固件版本号
*/
private String deviceVersion;
/**
* 备注
*/
private String remark;
}

View File

@ -0,0 +1,31 @@
package org.dromara.other.domain.dto.ys7device;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* @author lcj
* @date 2025/6/13 16:04
*/
@Data
public class OthYs7DeviceWithProjectReq implements Serializable {
@Serial
private static final long serialVersionUID = 5874710543055812819L;
/**
* 主键
*/
@NotNull(message = "主键不能为空")
private Long id;
/**
* 项目id
*/
@NotNull(message = "项目id不能为空")
private Long projectId;
}

View File

@ -0,0 +1,34 @@
package org.dromara.other.domain.enums;
import lombok.Getter;
/**
* @author lcj
* @date 2025/6/13 16:25
*/
@Getter
public enum OthVideoEncryptedEnum {
OFF("关闭", 0),
OPEN("开启", 1);
private final String text;
private final int value;
OthVideoEncryptedEnum(String text, int value) {
this.text = text;
this.value = value;
}
// 根据 value 获取对应的 text
public static String getTextByValue(int value) {
for (OthVideoEncryptedEnum type : values()) {
if (type.getValue() == value) {
return type.getText();
}
}
return null;
}
}

View File

@ -0,0 +1,57 @@
package org.dromara.other.domain.vo.devicepreset;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import org.dromara.other.domain.OthDevicePreset;
import java.io.Serial;
import java.io.Serializable;
/**
* 摄像头预置位视图对象 oth_device_preset
*
* @author lcj
* @date 2025-06-13
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = OthDevicePreset.class)
public class OthDevicePresetVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键id
*/
@ExcelProperty(value = "主键id")
private Long id;
/**
* 设备序列号
*/
@ExcelProperty(value = "设备序列号")
private String deviceSerial;
/**
* 通道号
*/
@ExcelProperty(value = "通道号")
private Long channelNo;
/**
* 预置点序号
*/
@ExcelProperty(value = "预置点序号")
private Long index;
/**
* 预置点
*/
@ExcelProperty(value = "预置点")
private String name;
}

View File

@ -0,0 +1,93 @@
package org.dromara.other.domain.vo.ys7device;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import org.dromara.other.domain.OthYs7Device;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
* 萤石摄像头视图对象 oth_ys7_device
*
* @author lcj
* @date 2025-06-13
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = OthYs7Device.class)
public class OthYs7DeviceVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键
*/
@ExcelProperty(value = "主键")
private Long id;
/**
* 项目id
*/
@ExcelProperty(value = "项目id")
private Long projectId;
/**
* 项目名称
*/
private String projectName;
/**
* 设备序列号
*/
@ExcelProperty(value = "设备序列号")
private String deviceSerial;
/**
* 设备名称
*/
@ExcelProperty(value = "设备名称")
private String deviceName;
/**
* 设备型号
*/
@ExcelProperty(value = "设备型号")
private String deviceType;
/**
* 设备在线状态(0离线 1在线)
*/
@ExcelProperty(value = "设备在线状态(0离线 1在线)")
private Integer status;
/**
* 固件版本号
*/
@ExcelProperty(value = "固件版本号")
private String deviceVersion;
/**
* 设备添加时间
*/
@ExcelProperty(value = "设备添加时间")
private Date deviceCreateTime;
/**
* 视频加密(0关闭 1开启)
*/
@ExcelProperty(value = "视频加密(0关闭 1开启)")
private Integer videoEncrypted;
/**
* 备注
*/
@ExcelProperty(value = "备注")
private String remark;
}

View File

@ -0,0 +1,15 @@
package org.dromara.other.mapper;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
import org.dromara.other.domain.OthDevicePreset;
import org.dromara.other.domain.vo.devicepreset.OthDevicePresetVo;
/**
* 摄像头预置位Mapper接口
*
* @author lcj
* @date 2025-06-13
*/
public interface OthDevicePresetMapper extends BaseMapperPlus<OthDevicePreset, OthDevicePresetVo> {
}

View File

@ -0,0 +1,15 @@
package org.dromara.other.mapper;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
import org.dromara.other.domain.OthYs7Device;
import org.dromara.other.domain.vo.ys7device.OthYs7DeviceVo;
/**
* 萤石摄像头Mapper接口
*
* @author lcj
* @date 2025-06-13
*/
public interface OthYs7DeviceMapper extends BaseMapperPlus<OthYs7Device, OthYs7DeviceVo> {
}

View File

@ -0,0 +1,98 @@
package org.dromara.other.service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.other.domain.OthDevicePreset;
import org.dromara.other.domain.dto.devicepreset.OthDevicePresetCreateReq;
import org.dromara.other.domain.dto.devicepreset.OthDevicePresetQueryReq;
import org.dromara.other.domain.dto.devicepreset.OthDevicePresetUpdateReq;
import org.dromara.other.domain.vo.devicepreset.OthDevicePresetVo;
import java.util.Collection;
import java.util.List;
/**
* 摄像头预置位Service接口
*
* @author lcj
* @date 2025-06-13
*/
public interface IOthDevicePresetService extends IService<OthDevicePreset> {
/**
* 查询摄像头预置位
*
* @param id 主键
* @return 摄像头预置位
*/
OthDevicePresetVo queryById(Long id);
/**
* 分页查询摄像头预置位列表
*
* @param req 查询条件
* @param pageQuery 分页参数
* @return 摄像头预置位分页列表
*/
TableDataInfo<OthDevicePresetVo> queryPageList(OthDevicePresetQueryReq req, PageQuery pageQuery);
/**
* 查询符合条件的摄像头预置位列表
*
* @param req 查询条件
* @return 摄像头预置位列表
*/
List<OthDevicePresetVo> queryList(OthDevicePresetQueryReq req);
/**
* 新增摄像头预置位
*
* @param req 摄像头预置位
* @return 新增摄像头预置位主键id
*/
Long insertByBo(OthDevicePresetCreateReq req);
/**
* 修改摄像头预置位
*
* @param req 摄像头预置位
* @return 是否修改成功
*/
Boolean updateByBo(OthDevicePresetUpdateReq req);
/**
* 校验并批量删除摄像头预置位信息
*
* @param ids 待删除的主键集合
* @param isValid 是否进行有效性校验
* @return 是否删除成功
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
/**
* 获取摄像头预置位视图
*
* @param devicePreset 摄像头预置位
* @return 摄像头预置位视图
*/
OthDevicePresetVo getVo(OthDevicePreset devicePreset);
/**
* 构建查询条件封装
*
* @param req 查询条件
* @return 查询条件封装
*/
LambdaQueryWrapper<OthDevicePreset> buildQueryWrapper(OthDevicePresetQueryReq req);
/**
* 获取摄像头预置位分页对象视图
*
* @param devicePresetPage 摄像头预置位分页对象
* @return 摄像头预置位分页对象视图
*/
Page<OthDevicePresetVo> getVoPage(Page<OthDevicePreset> devicePresetPage);
}

View File

@ -0,0 +1,133 @@
package org.dromara.other.service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.manager.ys7manager.vo.Ys7QueryDeviceResponseVo;
import org.dromara.other.domain.OthYs7Device;
import org.dromara.other.domain.dto.ys7device.OthYs7DeviceQueryReq;
import org.dromara.other.domain.dto.ys7device.OthYs7DeviceUpdateEncryptedReq;
import org.dromara.other.domain.dto.ys7device.OthYs7DeviceUpdateReq;
import org.dromara.other.domain.dto.ys7device.OthYs7DeviceWithProjectReq;
import org.dromara.other.domain.vo.ys7device.OthYs7DeviceVo;
import java.util.Collection;
import java.util.List;
/**
* 萤石摄像头Service接口
*
* @author lcj
* @date 2025-06-13
*/
public interface IOthYs7DeviceService extends IService<OthYs7Device> {
/**
* 查询萤石摄像头
*
* @param id 主键
* @return 萤石摄像头
*/
OthYs7DeviceVo queryById(Long id);
/**
* 分页查询萤石摄像头列表
*
* @param req 查询条件
* @param pageQuery 分页参数
* @return 萤石摄像头分页列表
*/
TableDataInfo<OthYs7DeviceVo> queryPageList(OthYs7DeviceQueryReq req, PageQuery pageQuery);
/**
* 查询符合条件的萤石摄像头列表
*
* @param req 查询条件
* @return 萤石摄像头列表
*/
List<OthYs7DeviceVo> queryList(OthYs7DeviceQueryReq req);
/**
* 修改萤石摄像头
*
* @param req 萤石摄像头
* @return 是否修改成功
*/
Boolean updateByBo(OthYs7DeviceUpdateReq req);
/**
* 设备分配项目
*
* @param req 萤石摄像头
* @return 是否分配成功
*/
Boolean updateWithProject(OthYs7DeviceWithProjectReq req);
/**
* 修改萤石摄像头视频加密
*
* @param req 萤石摄像头
* @return 是否修改成功
*/
Boolean updateVideoEncrypted(OthYs7DeviceUpdateEncryptedReq req);
/**
* 校验并批量删除萤石摄像头信息
*
* @param ids 待删除的主键集合
* @param isValid 是否进行有效性校验
* @return 是否删除成功
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
/**
* 获取萤石摄像头视图
*
* @param ys7Device 萤石摄像头
* @return 萤石摄像头视图
*/
OthYs7DeviceVo getVo(OthYs7Device ys7Device);
/**
* 构建查询条件封装
*
* @param req 查询条件
* @return 查询条件封装
*/
LambdaQueryWrapper<OthYs7Device> buildQueryWrapper(OthYs7DeviceQueryReq req);
/**
* 获取萤石摄像头分页对象视图
*
* @param ys7DevicePage 萤石摄像头分页对象
* @return 萤石摄像头分页对象视图
*/
Page<OthYs7DeviceVo> getVoPage(Page<OthYs7Device> ys7DevicePage);
/**
* 获取萤石摄像对象
*
* @param deviceResponseVo 萤石摄像数据
* @return 萤石摄像对象
*/
OthYs7Device getEntity(Ys7QueryDeviceResponseVo deviceResponseVo);
/**
* 获取萤石摄像对象列表
*
* @param deviceResponseVoList 萤石摄像数据列表
* @return 萤石摄像对象列表
*/
List<OthYs7Device> getEntityList(List<Ys7QueryDeviceResponseVo> deviceResponseVoList);
/**
* 根据云端数据保存或更新萤石摄像对象列表
*
* @param deviceResponseVoList 云端萤石摄像数据列表
* @return 是否有值发生更改
*/
Boolean saveOrUpdateByDeviceList(List<Ys7QueryDeviceResponseVo> deviceResponseVoList);
}

View File

@ -0,0 +1,214 @@
package org.dromara.other.service.impl;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import org.dromara.common.core.constant.HttpStatus;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.ObjectUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.other.domain.OthDevicePreset;
import org.dromara.other.domain.OthYs7Device;
import org.dromara.other.domain.dto.devicepreset.OthDevicePresetCreateReq;
import org.dromara.other.domain.dto.devicepreset.OthDevicePresetQueryReq;
import org.dromara.other.domain.dto.devicepreset.OthDevicePresetUpdateReq;
import org.dromara.other.domain.vo.devicepreset.OthDevicePresetVo;
import org.dromara.other.mapper.OthDevicePresetMapper;
import org.dromara.other.service.IOthDevicePresetService;
import org.dromara.other.service.IOthYs7DeviceService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import java.util.Collection;
import java.util.List;
/**
* 摄像头预置位Service业务层处理
*
* @author lcj
* @date 2025-06-13
*/
@Service
public class OthDevicePresetServiceImpl extends ServiceImpl<OthDevicePresetMapper, OthDevicePreset>
implements IOthDevicePresetService {
@Resource
private IOthYs7DeviceService othYs7DeviceService;
/**
* 查询摄像头预置位
*
* @param id 主键
* @return 摄像头预置位
*/
@Override
public OthDevicePresetVo queryById(Long id) {
OthDevicePreset devicePreset = this.getById(id);
if (devicePreset == null) {
throw new RuntimeException("摄像头预置位信息不存在");
}
return this.getVo(devicePreset);
}
/**
* 分页查询摄像头预置位列表
*
* @param req 查询条件
* @param pageQuery 分页参数
* @return 摄像头预置位分页列表
*/
@Override
public TableDataInfo<OthDevicePresetVo> queryPageList(OthDevicePresetQueryReq req, PageQuery pageQuery) {
Page<OthDevicePreset> result = this.page(pageQuery.build(), this.buildQueryWrapper(req));
return TableDataInfo.build(this.getVoPage(result));
}
/**
* 查询符合条件的摄像头预置位列表
*
* @param req 查询条件
* @return 摄像头预置位列表
*/
@Override
public List<OthDevicePresetVo> queryList(OthDevicePresetQueryReq req) {
LambdaQueryWrapper<OthDevicePreset> lqw = buildQueryWrapper(req);
return this.list(lqw).stream().map(this::getVo).toList();
}
/**
* 新增摄像头预置位
*
* @param req 摄像头预置位
* @return 新增摄像头预置位主键id
*/
@Override
public Long insertByBo(OthDevicePresetCreateReq req) {
OthDevicePreset devicePreset = new OthDevicePreset();
BeanUtils.copyProperties(req, devicePreset);
validEntityBeforeSave(devicePreset, true);
boolean result = this.save(devicePreset);
if (!result) {
throw new ServiceException("摄像头预置位信息新增失败", HttpStatus.ERROR);
}
return devicePreset.getId();
}
/**
* 修改摄像头预置位
*
* @param req 摄像头预置位
* @return 是否修改成功
*/
@Override
public Boolean updateByBo(OthDevicePresetUpdateReq req) {
OthDevicePreset devicePreset = new OthDevicePreset();
BeanUtils.copyProperties(req, devicePreset);
validEntityBeforeSave(devicePreset, false);
OthDevicePreset oldDevicePreset = this.getById(req.getId());
if (oldDevicePreset == null) {
throw new ServiceException("修改摄像头预置位信息失败,数据不存在", HttpStatus.NOT_FOUND);
}
boolean result = this.updateById(devicePreset);
if (!result) {
throw new ServiceException("摄像头预置位信息更新失败", HttpStatus.ERROR);
}
return true;
}
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(OthDevicePreset entity, Boolean create) {
//TODO 做一些数据校验,如唯一约束
String deviceSerial = entity.getDeviceSerial();
if (create) {
if (StringUtils.isBlank(deviceSerial)) {
throw new ServiceException("设备序列号不能为空", HttpStatus.BAD_REQUEST);
}
}
if (StringUtils.isNotBlank(deviceSerial)) {
Long count = othYs7DeviceService.lambdaQuery()
.eq(OthYs7Device::getDeviceSerial, deviceSerial)
.count();
if (count <= 0) {
throw new ServiceException("设备不存在", HttpStatus.BAD_REQUEST);
}
}
}
/**
* 校验并批量删除摄像头预置位信息
*
* @param ids 待删除的主键集合
* @param isValid 是否进行有效性校验
* @return 是否删除成功
*/
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if (isValid) {
//TODO 做一些业务上的校验,判断是否需要校验
}
return baseMapper.deleteByIds(ids) > 0;
}
/**
* 获取摄像头预置位视图
*
* @param devicePreset 摄像头预置位
* @return 摄像头预置位视图
*/
@Override
public OthDevicePresetVo getVo(OthDevicePreset devicePreset) {
OthDevicePresetVo vo = new OthDevicePresetVo();
if (devicePreset == null) {
return vo;
}
BeanUtils.copyProperties(devicePreset, vo);
return vo;
}
/**
* 构建查询条件封装
*
* @param req 查询条件
* @return 查询条件封装
*/
@Override
public LambdaQueryWrapper<OthDevicePreset> buildQueryWrapper(OthDevicePresetQueryReq req) {
LambdaQueryWrapper<OthDevicePreset> lqw = new LambdaQueryWrapper<>();
String deviceSerial = req.getDeviceSerial();
Long channelNo = req.getChannelNo();
Long index = req.getIndex();
String name = req.getName();
lqw.eq(StringUtils.isNotBlank(deviceSerial), OthDevicePreset::getDeviceSerial, deviceSerial);
lqw.eq(ObjectUtils.isNotEmpty(channelNo), OthDevicePreset::getChannelNo, channelNo);
lqw.eq(ObjectUtils.isNotEmpty(index), OthDevicePreset::getIndex, index);
lqw.like(StringUtils.isNotBlank(name), OthDevicePreset::getName, name);
return lqw;
}
/**
* 获取摄像头预置位分页对象视图
*
* @param devicePresetPage 摄像头预置位分页对象
* @return 摄像头预置位分页对象视图
*/
@Override
public Page<OthDevicePresetVo> getVoPage(Page<OthDevicePreset> devicePresetPage) {
List<OthDevicePreset> devicePresetList = devicePresetPage.getRecords();
Page<OthDevicePresetVo> devicePresetVoPage = new Page<>(
devicePresetPage.getCurrent(),
devicePresetPage.getSize(),
devicePresetPage.getTotal());
if (CollUtil.isEmpty(devicePresetList)) {
return devicePresetVoPage;
}
List<OthDevicePresetVo> devicePresetVoList = devicePresetList.stream().map(this::getVo).toList();
devicePresetVoPage.setRecords(devicePresetVoList);
return devicePresetVoPage;
}
}

View File

@ -0,0 +1,407 @@
package org.dromara.other.service.impl;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.constant.HttpStatus;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.ObjectUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.manager.ys7manager.Ys7Manager;
import org.dromara.manager.ys7manager.Ys7RequestUtils;
import org.dromara.manager.ys7manager.vo.Ys7QueryDeviceResponseVo;
import org.dromara.other.domain.OthYs7Device;
import org.dromara.other.domain.dto.ys7device.OthYs7DeviceQueryReq;
import org.dromara.other.domain.dto.ys7device.OthYs7DeviceUpdateEncryptedReq;
import org.dromara.other.domain.dto.ys7device.OthYs7DeviceUpdateReq;
import org.dromara.other.domain.dto.ys7device.OthYs7DeviceWithProjectReq;
import org.dromara.other.domain.enums.OthVideoEncryptedEnum;
import org.dromara.other.domain.vo.ys7device.OthYs7DeviceVo;
import org.dromara.other.mapper.OthYs7DeviceMapper;
import org.dromara.other.service.IOthYs7DeviceService;
import org.dromara.project.domain.BusProject;
import org.dromara.project.service.IBusProjectService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* 萤石摄像头Service业务层处理
*
* @author lcj
* @date 2025-06-13
*/
@Slf4j
@Service
public class OthYs7DeviceServiceImpl extends ServiceImpl<OthYs7DeviceMapper, OthYs7Device>
implements IOthYs7DeviceService {
@Resource
private IBusProjectService projectService;
@Resource
private Ys7Manager ys7Manager;
/**
* 查询萤石摄像头
*
* @param id 主键
* @return 萤石摄像头
*/
@Override
public OthYs7DeviceVo queryById(Long id) {
OthYs7Device ys7Device = this.getById(id);
if (ys7Device == null) {
throw new ServiceException("萤石摄像头信息不存在", HttpStatus.NOT_FOUND);
}
return this.getVo(ys7Device);
}
/**
* 分页查询萤石摄像头列表
*
* @param req 查询条件
* @param pageQuery 分页参数
* @return 萤石摄像头分页列表
*/
@Override
public TableDataInfo<OthYs7DeviceVo> queryPageList(OthYs7DeviceQueryReq req, PageQuery pageQuery) {
LambdaQueryWrapper<OthYs7Device> lqw = buildQueryWrapper(req);
Page<OthYs7Device> result = this.page(pageQuery.build(), lqw);
return TableDataInfo.build(this.getVoPage(result));
}
/**
* 查询符合条件的萤石摄像头列表
*
* @param req 查询条件
* @return 萤石摄像头列表
*/
@Override
public List<OthYs7DeviceVo> queryList(OthYs7DeviceQueryReq req) {
LambdaQueryWrapper<OthYs7Device> lqw = buildQueryWrapper(req);
return this.list(lqw).stream().map(this::getVo).toList();
}
/**
* 修改萤石摄像头
*
* @param req 萤石摄像头
* @return 是否修改成功
*/
@Override
public Boolean updateByBo(OthYs7DeviceUpdateReq req) {
// 将实体类和 DTO 进行转换
OthYs7Device ys7Device = new OthYs7Device();
BeanUtils.copyProperties(req, ys7Device);
// 数据校验
OthYs7Device oldYs7Device = this.getById(req.getId());
if (oldYs7Device == null) {
throw new ServiceException("萤石摄像头信息不存在", HttpStatus.NOT_FOUND);
}
validEntityBeforeSave(ys7Device);
// 判断是否更新名称
String deviceName = req.getDeviceName();
if (deviceName != null && !deviceName.equals(oldYs7Device.getDeviceName())) {
Long count = this.lambdaQuery()
.eq(OthYs7Device::getDeviceName, req.getDeviceName())
.count();
if (count > 0) {
throw new ServiceException("已存在同名萤石摄像头", HttpStatus.CONFLICT);
}
String token = ys7Manager.getToken();
Boolean result = Ys7RequestUtils.updateDeviceName(token, oldYs7Device.getDeviceSerial(), deviceName);
if (!result) {
throw new ServiceException("更新云端萤石摄像头名称异常", HttpStatus.ERROR);
}
}
boolean result = this.updateById(ys7Device);
if (!result) {
throw new ServiceException("更新萤石摄像头信息异常", HttpStatus.ERROR);
}
return true;
}
/**
* 设备分配项目
*
* @param req 萤石摄像头
* @return 是否分配成功
*/
@Override
public Boolean updateWithProject(OthYs7DeviceWithProjectReq req) {
Long id = req.getId();
Long projectId = req.getProjectId();
// 参数校验
if (id == null || projectId == null) {
throw new ServiceException("参数为空", HttpStatus.BAD_REQUEST);
}
OthYs7Device ys7Device = this.getById(id);
if (ys7Device == null) {
throw new ServiceException("萤石摄像头信息不存在", HttpStatus.NOT_FOUND);
}
BusProject project = projectService.getById(projectId);
if (project == null) {
throw new ServiceException("项目信息不存在", HttpStatus.NOT_FOUND);
}
// 权限校验
Long userId = LoginHelper.getUserId();
projectService.validAuth(projectId, userId);
// 更新
boolean update = this.lambdaUpdate()
.eq(OthYs7Device::getId, id)
.set(OthYs7Device::getProjectId, projectId)
.update();
if (!update) {
throw new ServiceException("更新萤石摄像头信息异常", HttpStatus.ERROR);
}
return true;
}
/**
* 修改萤石摄像头视频加密
*
* @param req 萤石摄像头
* @return 是否修改成功
*/
@Override
public Boolean updateVideoEncrypted(OthYs7DeviceUpdateEncryptedReq req) {
Long id = req.getId();
Integer videoEncrypted = req.getVideoEncrypted();
// 参数校验
if (id == null || videoEncrypted == null) {
throw new ServiceException("参数为空", HttpStatus.BAD_REQUEST);
}
OthYs7Device ys7Device = this.getById(id);
if (ys7Device == null) {
throw new ServiceException("萤石摄像头信息不存在", HttpStatus.NOT_FOUND);
}
if (videoEncrypted.equals(ys7Device.getVideoEncrypted())) {
return true;
}
String text = OthVideoEncryptedEnum.getTextByValue(videoEncrypted);
if (text == null) {
throw new ServiceException("参数错误,未知状态", HttpStatus.BAD_REQUEST);
}
boolean update = this.lambdaUpdate()
.eq(OthYs7Device::getId, id)
.set(OthYs7Device::getVideoEncrypted, videoEncrypted)
.update();
if (!update) {
throw new ServiceException("更新萤石摄像头信息异常", HttpStatus.ERROR);
}
return true;
}
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(OthYs7Device entity) {
//TODO 做一些数据校验,如唯一约束
Long projectId = entity.getProjectId();
if (projectId != null && projectId != 0) {
if (projectService.getById(projectId) == null) {
throw new ServiceException("对应项目不存在", HttpStatus.NOT_FOUND);
}
}
}
/**
* 校验并批量删除萤石摄像头信息
*
* @param ids 待删除的主键集合
* @param isValid 是否进行有效性校验
* @return 是否删除成功
*/
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if (isValid) {
//TODO 做一些业务上的校验,判断是否需要校验
}
return baseMapper.deleteByIds(ids) > 0;
}
/**
* 获取萤石摄像头视图
*
* @param ys7Device 萤石摄像头
* @return 萤石摄像头视图
*/
@Override
public OthYs7DeviceVo getVo(OthYs7Device ys7Device) {
// 对象转封装类
OthYs7DeviceVo ys7DeviceVo = new OthYs7DeviceVo();
if (ys7Device == null) {
return ys7DeviceVo;
}
BeanUtils.copyProperties(ys7Device, ys7DeviceVo);
Long projectId = ys7Device.getProjectId();
if (projectId != null && !projectId.equals(0L)) {
BusProject project = projectService.getById(projectId);
ys7DeviceVo.setProjectName(project.getProjectName());
}
return ys7DeviceVo;
}
/**
* 构建查询条件封装
*
* @param req 查询条件
* @return 查询条件封装
*/
@Override
public LambdaQueryWrapper<OthYs7Device> buildQueryWrapper(OthYs7DeviceQueryReq req) {
LambdaQueryWrapper<OthYs7Device> lqw = new LambdaQueryWrapper<>();
String deviceSerial = req.getDeviceSerial();
Long projectId = req.getProjectId();
String deviceName = req.getDeviceName();
String deviceType = req.getDeviceType();
String deviceVersion = req.getDeviceVersion();
Long status = req.getStatus();
lqw.eq(ObjectUtils.isNotEmpty(projectId), OthYs7Device::getProjectId, projectId)
.or()
.eq(OthYs7Device::getProjectId, 0L);
lqw.eq(ObjectUtils.isNotEmpty(status), OthYs7Device::getStatus, status);
lqw.like(StringUtils.isNotBlank(deviceName), OthYs7Device::getDeviceName, deviceName);
lqw.like(StringUtils.isNotBlank(deviceType), OthYs7Device::getDeviceType, deviceType);
lqw.like(StringUtils.isNotBlank(deviceSerial), OthYs7Device::getDeviceSerial, deviceSerial);
lqw.like(StringUtils.isNotBlank(deviceVersion), OthYs7Device::getDeviceVersion, deviceVersion);
lqw.orderByDesc(OthYs7Device::getProjectId);
return lqw;
}
/**
* 获取萤石摄像头分页对象视图
*
* @param ys7DevicePage 萤石摄像头分页对象
* @return 萤石摄像头分页对象视图
*/
@Override
public Page<OthYs7DeviceVo> getVoPage(Page<OthYs7Device> ys7DevicePage) {
List<OthYs7Device> ys7DeviceList = ys7DevicePage.getRecords();
Page<OthYs7DeviceVo> ys7DeviceVoPage = new Page<>(
ys7DevicePage.getCurrent(),
ys7DevicePage.getSize(),
ys7DevicePage.getTotal());
if (CollUtil.isEmpty(ys7DeviceList)) {
return ys7DeviceVoPage;
}
// 获取项目列表
Set<Long> projectIdList = ys7DeviceList.stream().map(OthYs7Device::getProjectId).collect(Collectors.toSet());
List<BusProject> projectList = projectService.lambdaQuery()
.select(BusProject::getId, BusProject::getProjectName)
.in(BusProject::getId, projectIdList)
.list();
Map<Long, BusProject> projectMap = projectList.stream().collect(Collectors.toMap(BusProject::getId, project -> project));
// 对象列表 => 封装对象列表
List<OthYs7DeviceVo> ys7DeviceVoList = ys7DeviceList.stream().map(ys7Device -> {
OthYs7DeviceVo ys7DeviceVo = new OthYs7DeviceVo();
BeanUtils.copyProperties(ys7Device, ys7DeviceVo);
Long projectId = ys7Device.getProjectId();
if (projectId != null && !projectId.equals(0L)) {
BusProject project = projectMap.get(projectId);
ys7DeviceVo.setProjectName(project.getProjectName());
}
return ys7DeviceVo;
}).toList();
ys7DeviceVoPage.setRecords(ys7DeviceVoList);
return ys7DeviceVoPage;
}
/**
* 获取萤石摄像对象
*
* @param deviceResponseVo 萤石摄像数据
* @return 萤石摄像对象
*/
@Override
public OthYs7Device getEntity(Ys7QueryDeviceResponseVo deviceResponseVo) {
OthYs7Device ys7Device = new OthYs7Device();
if (deviceResponseVo == null) {
return ys7Device;
}
ys7Device.setDeviceSerial(deviceResponseVo.getDeviceSerial());
ys7Device.setDeviceName(deviceResponseVo.getDeviceName());
ys7Device.setDeviceType(deviceResponseVo.getDeviceType());
ys7Device.setStatus(deviceResponseVo.getStatus());
ys7Device.setDefence(Long.valueOf(deviceResponseVo.getDefence()));
ys7Device.setDeviceVersion(deviceResponseVo.getDeviceVersion());
ys7Device.setPosition(deviceResponseVo.getNetAddress());
ys7Device.setDeviceCreateTime(new Date(deviceResponseVo.getAddTime()));
ys7Device.setDeviceUpdateTime(new Date(deviceResponseVo.getUpdateTime()));
ys7Device.setRiskLevel(deviceResponseVo.getRiskLevel());
return ys7Device;
}
/**
* 获取萤石摄像对象列表
*
* @param deviceResponseVoList 萤石摄像数据列表
* @return 萤石摄像对象列表
*/
@Override
public List<OthYs7Device> getEntityList(List<Ys7QueryDeviceResponseVo> deviceResponseVoList) {
if (CollUtil.isEmpty(deviceResponseVoList)) {
return List.of();
}
return deviceResponseVoList.stream().map(this::getEntity).toList();
}
/**
* 根据云端数据保存或更新萤石摄像对象列表
*
* @param deviceResponseVoList 云端萤石摄像数据列表
* @return 是否有值发生更改
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean saveOrUpdateByDeviceList(List<Ys7QueryDeviceResponseVo> deviceResponseVoList) {
if (deviceResponseVoList == null) {
return false;
}
List<OthYs7Device> deviceList = this.getEntityList(deviceResponseVoList);
// 查询数据库中的数据并构建 Map<deviceSerial, OthYs7Device>
Map<String, OthYs7Device> entityMap = this.list().stream()
.collect(Collectors.toMap(
OthYs7Device::getDeviceSerial,
Function.identity(),
(a, b) -> a));
// 记录日志
StringBuffer updateLog = new StringBuffer();
StringBuffer saveLog = new StringBuffer();
// 遍历设备列表,设置已存在的 id
List<OthYs7Device> resultList = deviceList.stream()
.peek(device -> {
OthYs7Device existing = entityMap.get(device.getDeviceSerial());
if (existing != null) {
device.setId(existing.getId());
updateLog.append("[")
.append(device.getDeviceName())
.append("")
.append(device.getDeviceSerial())
.append("]");
} else {
saveLog.append("[")
.append(device.getDeviceName())
.append("")
.append(device.getDeviceSerial())
.append("]");
}
})
.toList();
log.info("需新增信息设备:{}", saveLog);
log.info("需修改信息设备:{}", updateLog);
// 更新或保存设备列表
return saveOrUpdateBatch(resultList);
}
}

View File

@ -8,6 +8,11 @@ import java.util.List;
*/
public interface PgsProgressCategoryConstant {
/**
* 顶级父级id
*/
Long TOP_PARENT_ID = 0L;
/**
* 项目公共进度类别ID
*/

View File

@ -1,7 +1,6 @@
package org.dromara.progress.domain;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
@ -9,7 +8,6 @@ import org.dromara.common.mybatis.core.domain.BaseEntity;
import java.io.Serial;
import java.math.BigDecimal;
import java.util.Date;
/**
* 进度类别对象 pgs_progress_category
@ -46,6 +44,11 @@ public class PgsProgressCategory extends BaseEntity {
*/
private Long matrixId;
/**
* 方阵名称
*/
private String matrixName;
/**
* 类别名称
*/
@ -91,15 +94,4 @@ public class PgsProgressCategory extends BaseEntity {
*/
private String remark;
/**
* 删除时间
*/
private Date deletedAt;
/**
* 是否删除0正常 1删除
*/
@TableLogic
private Long isDelete;
}

View File

@ -27,6 +27,11 @@ public class PgsProgressCategoryMatrixVo implements Serializable {
*/
private Long matrixId;
/**
* 方阵名称
*/
private String name;
/**
* 总数量/百分比
*/

View File

@ -24,6 +24,11 @@ public class PgsProgressCategoryProjectVo implements Serializable {
*/
private Long projectId;
/**
* 项目名称
*/
private String name;
/**
* 总数量/百分比
*/

View File

@ -28,6 +28,11 @@ public class PgsProgressCategorySubProjectVo implements Serializable {
*/
private Long subProjectId;
/**
* 子项目名称
*/
private String name;
/**
* 总数量/百分比
*/

View File

@ -2,6 +2,7 @@ package org.dromara.progress.service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.IService;
import org.dromara.facility.domain.FacMatrix;
import org.dromara.progress.domain.PgsProgressCategory;
import org.dromara.progress.domain.dto.progresscategory.PgsProgressCategoryCreateReq;
import org.dromara.progress.domain.dto.progresscategory.PgsProgressCategoryQueryReq;
@ -98,11 +99,12 @@ public interface IPgsProgressCategoryService extends IService<PgsProgressCategor
/**
* 根据模板创建进度类别
*
* @param projectId 项目id
* @param matrixIds 方阵id列表
* @param projectId 项目id
* @param matrixList 方阵列表
* @param oldMatrixList 旧方阵列表
* @return 是否创建成功
*/
Boolean insertByTemplate(Long projectId, List<Long> matrixIds);
Boolean insertByTemplate(Long projectId, List<FacMatrix> matrixList, List<FacMatrix> oldMatrixList);
/**
* 根据id获取进度类别坐标信息

View File

@ -113,7 +113,13 @@ public class PgsProgressCategoryServiceImpl extends ServiceImpl<PgsProgressCateg
*/
@Override
public List<PgsProgressCategoryVo> queryList(PgsProgressCategoryQueryReq req) {
List<PgsProgressCategory> list = this.list(this.buildQueryWrapper(req));
Long matrixId = req.getMatrixId();
if (matrixService.getById(matrixId) == null) {
throw new ServiceException("方阵不存在", HttpStatus.BAD_REQUEST);
}
List<PgsProgressCategory> list = this.lambdaQuery()
.eq(PgsProgressCategory::getMatrixId, matrixId)
.list();
return this.getVoList(list);
}
@ -275,7 +281,7 @@ public class PgsProgressCategoryServiceImpl extends ServiceImpl<PgsProgressCateg
Long projectId = req.getProjectId();
Long matrixId = req.getMatrixId();
// 精确查询
lqw.in(ObjectUtils.isNotEmpty(projectId), PgsProgressCategory::getProjectId, projectId);
lqw.eq(ObjectUtils.isNotEmpty(projectId), PgsProgressCategory::getProjectId, projectId);
lqw.eq(ObjectUtils.isNotEmpty(matrixId), PgsProgressCategory::getMatrixId, matrixId);
return lqw;
}
@ -324,13 +330,15 @@ public class PgsProgressCategoryServiceImpl extends ServiceImpl<PgsProgressCateg
/**
* 根据模板创建进度类别
*
* @param projectId 项目id
* @param matrixIds 方阵id列表
* @param projectId 项目id
* @param matrixList 方阵列表
* @param oldMatrixList 旧方阵列表
* @return 是否创建成功
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean insertByTemplate(Long projectId, List<Long> matrixIds) {
public Boolean insertByTemplate(Long projectId, List<FacMatrix> matrixList, List<FacMatrix> oldMatrixList) {
List<Long> oldMatrixIdList = oldMatrixList.stream().map(FacMatrix::getId).toList();
// 获取模板进度类别
List<PgsProgressCategoryTemplate> categoryTemplateList = pgsProgressCategoryTemplateService.lambdaQuery()
.in(PgsProgressCategoryTemplate::getProjectId, projectId, PgsProgressCategoryConstant.PUBLIC_PROJECT_ID)
@ -339,10 +347,45 @@ public class PgsProgressCategoryServiceImpl extends ServiceImpl<PgsProgressCateg
if (CollUtil.isEmpty(categoryTemplateList)) {
throw new ServiceException("对应模板进度类别不存在", HttpStatus.NOT_FOUND);
}
// 获取百分比设施数据
Map<String, List<PgsProgressCategory>> oldPercentageCategoryMap = new HashMap<>();
Map<Long, List<PgsProgressPlan>> oldPlanMap = new HashMap<>();
Map<Long, List<PgsProgressPlanDetail>> oldPlanDetailMap = new HashMap<>();
if (CollUtil.isNotEmpty(oldMatrixList)) {
List<PgsProgressCategory> oldPercentageCategoryList = this.lambdaQuery()
.in(PgsProgressCategory::getMatrixId, oldMatrixIdList)
.ne(PgsProgressCategory::getPid, PgsProgressCategoryConstant.TOP_PARENT_ID)
.eq(PgsProgressCategory::getUnitType, PgsProgressUnitTypeEnum.PERCENTAGE.getValue())
.list();
oldPercentageCategoryMap = oldPercentageCategoryList.stream()
.collect(Collectors.groupingBy(item -> item.getMatrixName() + "_" + item.getWorkType()));
// 获取百分比设施计划数据
List<Long> oldPercentageCategoryIdList = oldPercentageCategoryList.stream().map(PgsProgressCategory::getId).toList();
if (CollUtil.isNotEmpty(oldPercentageCategoryIdList)) {
List<PgsProgressPlan> oldPlanList = progressPlanService.lambdaQuery()
.select(PgsProgressPlan::getId, PgsProgressPlan::getProgressCategoryId)
.in(PgsProgressPlan::getProgressCategoryId, oldPercentageCategoryIdList)
.list();
oldPlanMap = oldPlanList.stream()
.collect(Collectors.groupingBy(PgsProgressPlan::getProgressCategoryId));
// 获取百分比设施计划详情数据
List<Long> oldPlanIdList = oldPlanList.stream().map(PgsProgressPlan::getId).toList();
if (CollUtil.isNotEmpty(oldPlanIdList)) {
List<PgsProgressPlanDetail> oldPlanDetailList = progressPlanDetailService.lambdaQuery()
.in(PgsProgressPlanDetail::getProgressPlanId, oldPlanIdList)
.list();
oldPlanDetailMap = oldPlanDetailList.stream()
.collect(Collectors.groupingBy(PgsProgressPlanDetail::getProgressPlanId));
}
}
}
// 需修改、保存的数据
List<PgsProgressCategory> newList = new ArrayList<>();
List<FacPercentageFacility> percentageFacilityList = new ArrayList<>();
List<PgsProgressPlan> newPlanList = new ArrayList<>();
List<PgsProgressPlanDetail> newPlanDetailList = new ArrayList<>();
// 每个 matrixId 对应一套新的 ID 映射
for (Long matrixId : matrixIds) {
for (FacMatrix matrix : matrixList) {
// templateId -> newId
Map<Long, Long> localIdMap = new HashMap<>();
List<PgsProgressCategory> localList = new ArrayList<>();
@ -355,17 +398,50 @@ public class PgsProgressCategoryServiceImpl extends ServiceImpl<PgsProgressCateg
newCategory.setUnitType(template.getUnitType());
newCategory.setWorkType(template.getWorkType());
newCategory.setProjectId(projectId);
newCategory.setMatrixId(matrixId);
newCategory.setMatrixId(matrix.getId());
newCategory.setMatrixName(matrix.getMatrixName());
newCategory.setRemark(template.getRemark());
// 先临时设置旧 pid
newCategory.setPid(template.getPid());
localList.add(newCategory);
// 创建百分比设施
if (template.getPid() != 0 && template.getUnitType().equals(PgsProgressUnitTypeEnum.PERCENTAGE.getValue())) {
String mapKey = matrix.getMatrixName() + "_" + template.getWorkType();
// 填充数据
if (CollUtil.isNotEmpty(oldPercentageCategoryMap) && oldPercentageCategoryMap.containsKey(mapKey)) {
PgsProgressCategory oldPercentageCategory = oldPercentageCategoryMap.get(mapKey).getFirst();
if (CollUtil.isNotEmpty(oldPlanMap) && oldPlanMap.containsKey(oldPercentageCategory.getId())) {
List<PgsProgressPlan> planList = oldPlanMap.get(oldPercentageCategory.getId());
// 填充计划数据
for (PgsProgressPlan plan : planList) {
PgsProgressPlan newPlan = new PgsProgressPlan();
Long planId = plan.getId();
newPlan.setId(planId);
newPlan.setProjectId(projectId);
newPlan.setMatrixId(matrix.getId());
newPlan.setProgressCategoryId(newId);
newPlanList.add(newPlan);
// 填充计划详情数据
if (CollUtil.isNotEmpty(oldPlanDetailMap) && oldPlanDetailMap.containsKey(planId)) {
List<PgsProgressPlanDetail> planDetailList = oldPlanDetailMap.get(planId);
for (PgsProgressPlanDetail planDetail : planDetailList) {
PgsProgressPlanDetail newPlanDetail = new PgsProgressPlanDetail();
newPlanDetail.setId(planDetail.getId());
newPlanDetail.setProgressCategoryId(newId);
newPlanDetailList.add(newPlanDetail);
}
}
}
}
newCategory.setCompleted(oldPercentageCategory.getCompleted());
newCategory.setPlanTotal(oldPercentageCategory.getPlanTotal());
newCategory.setIsDelay(oldPercentageCategory.getIsDelay());
newCategory.setStatus(oldPercentageCategory.getStatus());
}
newCategory.setTotal(BigDecimal.valueOf(100));
FacPercentageFacility percentageFacility = new FacPercentageFacility();
percentageFacility.setProjectId(projectId);
percentageFacility.setMatrixId(matrixId);
percentageFacility.setMatrixId(matrix.getId());
percentageFacility.setProgressCategoryId(newId);
percentageFacility.setProgressCategoryName(template.getName());
percentageFacilityList.add(percentageFacility);
@ -380,10 +456,31 @@ public class PgsProgressCategoryServiceImpl extends ServiceImpl<PgsProgressCateg
}
newList.addAll(localList);
}
// 删除旧进度类别
LambdaQueryWrapper<PgsProgressCategory> lqw = new LambdaQueryWrapper<>();
lqw.eq(PgsProgressCategory::getProjectId, projectId);
long oldCategoryCount = this.count(lqw);
if (oldCategoryCount > 0) {
boolean remove = this.remove(lqw);
if (!remove) {
throw new ServiceException("删除旧进度类别失败", HttpStatus.ERROR);
}
}
// 批量保存新进度类别
boolean result = this.saveBatch(newList);
if (!result) {
throw new ServiceException("创建进度类别失败", HttpStatus.ERROR);
}
// 删除旧数据
LambdaQueryWrapper<FacPercentageFacility> percentageFacilityLqw = new LambdaQueryWrapper<>();
percentageFacilityLqw.eq(FacPercentageFacility::getMatrixId, oldMatrixIdList);
long count = percentageFacilityService.count(percentageFacilityLqw);
if (count > 0) {
boolean remove = percentageFacilityService.remove(percentageFacilityLqw);
if (!remove) {
throw new ServiceException("删除旧百分比设施数据失败", HttpStatus.ERROR);
}
}
// 保存百分比设施
if (CollUtil.isNotEmpty(percentageFacilityList)) {
boolean save = percentageFacilityService.saveBatch(percentageFacilityList);
@ -391,6 +488,20 @@ public class PgsProgressCategoryServiceImpl extends ServiceImpl<PgsProgressCateg
throw new ServiceException("创建设施失败", HttpStatus.ERROR);
}
}
// 修改百分比设施计划
if (CollUtil.isNotEmpty(newPlanList)) {
boolean save = progressPlanService.updateBatchById(newPlanList);
if (!save) {
throw new ServiceException("修改设施计划失败", HttpStatus.ERROR);
}
}
// 修改百分比设施计划详情
if (CollUtil.isNotEmpty(newPlanDetailList)) {
boolean save = progressPlanDetailService.updateBatchById(newPlanDetailList);
if (!save) {
throw new ServiceException("修改设施计划详情失败", HttpStatus.ERROR);
}
}
return true;
}
@ -515,7 +626,7 @@ public class PgsProgressCategoryServiceImpl extends ServiceImpl<PgsProgressCateg
List<Long> subProjectIdList = subProjectList.stream().map(BusProject::getId).toList();
// 获取方阵信息
List<FacMatrix> matrixList = matrixService.lambdaQuery()
.select(FacMatrix::getId)
.select(FacMatrix::getId, FacMatrix::getProjectId)
.in(FacMatrix::getProjectId, subProjectIdList)
.list();
if (CollUtil.isEmpty(matrixList)) {
@ -527,7 +638,12 @@ public class PgsProgressCategoryServiceImpl extends ServiceImpl<PgsProgressCateg
.collect(Collectors.groupingBy(FacMatrix::getProjectId));
// 获取每个方阵下的进度类别信息
List<PgsProgressCategory> progressCategoryList = this.lambdaQuery()
.select(PgsProgressCategory::getId, PgsProgressCategory::getStatus, PgsProgressCategory::getMatrixId)
.select(PgsProgressCategory::getId,
PgsProgressCategory::getStatus,
PgsProgressCategory::getMatrixId,
PgsProgressCategory::getTotal,
PgsProgressCategory::getPlanTotal,
PgsProgressCategory::getCompleted)
.in(PgsProgressCategory::getMatrixId, matrixIdList)
.list();
// 分组matrixId -> categoryList
@ -573,6 +689,7 @@ public class PgsProgressCategoryServiceImpl extends ServiceImpl<PgsProgressCateg
// 构建子项目VO
PgsProgressCategorySubProjectVo subProjectVo = new PgsProgressCategorySubProjectVo();
subProjectVo.setSubProjectId(subProjectId);
subProjectVo.setName(subProject.getProjectName());
subProjectVo.setTotal(total);
subProjectVo.setCompleted(completed);
subProjectVo.setPlanTotal(planTotal);
@ -588,6 +705,7 @@ public class PgsProgressCategoryServiceImpl extends ServiceImpl<PgsProgressCateg
// 构建项目VO
PgsProgressCategoryProjectVo projectVo = new PgsProgressCategoryProjectVo();
projectVo.setProjectId(projectId);
projectVo.setName(project.getProjectName());
projectVo.setTotal(totalAll);
projectVo.setCompleted(completedAll);
projectVo.setPlanTotal(planTotalAll);

View File

@ -248,9 +248,10 @@ public class PgsProgressPlanDetailServiceImpl extends ServiceImpl<PgsProgressPla
}
Long number = progressPlanDetail.getFinishedNumber();
Long finishedNumberTotal = progressPlan.getFinishedNumber();
if (finishedNumberTotal + finishedNumber > progressPlan.getPlanNumber()) {
// todo 是否判断完成百分比是否大于计划进度
/* if (finishedNumberTotal + finishedNumber > progressPlan.getPlanNumber()) {
throw new ServiceException("完成百分比不能大于计划进度", HttpStatus.BAD_REQUEST);
}
}*/
progressPlanDetail.setFinishedNumber(finishedNumber);
// 更新
boolean update = this.updateById(progressPlanDetail);

View File

@ -61,6 +61,16 @@ public class BusProjectController extends BaseController {
return R.ok(projectService.querySubList(id));
}
/**
* 查询项目下的子项目方阵列表
*/
@SaCheckPermission("project:project:list")
@GetMapping("/list/sub/matrix/{id}")
public R<List<BusSubProjectMatrixVo>> listSubProjectMatrix(@NotNull(message = "项目id不能为空")
@PathVariable Long id) {
return R.ok(projectService.querySubProjectMatrixList(id));
}
/**
* 导出项目列表
*/

View File

@ -0,0 +1,35 @@
package org.dromara.project.domain.vo.project;
import lombok.Data;
import org.dromara.facility.domain.vo.matrix.FacMatrixBySubProjectVo;
import java.io.Serial;
import java.io.Serializable;
import java.util.List;
/**
* @author lcj
* @date 2025/6/10 15:06
*/
@Data
public class BusSubProjectMatrixVo implements Serializable {
@Serial
private static final long serialVersionUID = 5817777295498328412L;
/**
* id
*/
private Long projectId;
/**
* 项目名称
*/
private String name;
/**
* 方阵列表
*/
private List<FacMatrixBySubProjectVo> children;
}

View File

@ -56,6 +56,14 @@ public interface IBusProjectService extends IService<BusProject> {
*/
List<BusSubProjectVo> querySubList(Long id);
/**
* 获取项目子项目方阵信息
*
* @param id 项目id
* @return 子项目方阵信息列表
*/
List<BusSubProjectMatrixVo> querySubProjectMatrixList(Long id);
/**
* 查询当前登录用户项目列表以及项目列表下的分包公司列表
*

View File

@ -26,6 +26,9 @@ import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.facility.domain.FacMatrix;
import org.dromara.facility.domain.vo.matrix.FacMatrixBySubProjectVo;
import org.dromara.facility.service.IFacMatrixService;
import org.dromara.manager.weathermanager.WeatherConstant;
import org.dromara.manager.weathermanager.WeatherManager;
import org.dromara.project.constant.BusProjectConstant;
@ -82,6 +85,10 @@ public class BusProjectServiceImpl extends ServiceImpl<BusProjectMapper, BusProj
@Resource
private StringRedisTemplate stringRedisTemplate;
@Lazy
@Resource
private IFacMatrixService matrixService;
private final Cache<String, String> WEATHER_CACHE =
Caffeine.newBuilder().initialCapacity(1024)
.maximumSize(10000L)
@ -164,6 +171,62 @@ public class BusProjectServiceImpl extends ServiceImpl<BusProjectMapper, BusProj
}).toList();
}
/**
* 获取项目子项目方阵信息
*
* @param id 项目id
* @return 子项目方阵信息列表
*/
@Override
public List<BusSubProjectMatrixVo> querySubProjectMatrixList(Long id) {
// 获取项目信息
BusProject project = this.getById(id);
if (project == null) {
throw new ServiceException("查询项目不存在", HttpStatus.NOT_FOUND);
}
// 获取项目下的子项目信息
List<BusProject> subProjectList = this.lambdaQuery()
.select(BusProject::getId, BusProject::getProjectName)
.eq(BusProject::getPId, id)
.list();
if (CollUtil.isEmpty(subProjectList)) {
return List.of();
}
List<Long> subProjectIdList = subProjectList.stream().map(BusProject::getId).toList();
// 获取方阵信息
List<FacMatrix> matrixList = matrixService.lambdaQuery()
.select(FacMatrix::getId, FacMatrix::getProjectId, FacMatrix::getMatrixName)
.in(FacMatrix::getProjectId, subProjectIdList)
.list();
if (CollUtil.isEmpty(matrixList)) {
return subProjectList.stream().map(subProject -> {
BusSubProjectMatrixVo vo = new BusSubProjectMatrixVo();
vo.setProjectId(subProject.getId());
vo.setName(subProject.getProjectName());
vo.setChildren(List.of());
return vo;
}).toList();
}
// 获取子项目下的方阵信息
Map<Long, List<FacMatrix>> matrixMap = matrixList.stream()
.collect(Collectors.groupingBy(FacMatrix::getProjectId));
return subProjectList.stream().map(subProject -> {
BusSubProjectMatrixVo vo = new BusSubProjectMatrixVo();
vo.setProjectId(subProject.getId());
vo.setName(subProject.getProjectName());
if (matrixMap.containsKey(subProject.getId())) {
List<FacMatrix> subProjectMatrix = matrixMap.get(subProject.getId());
vo.setChildren(subProjectMatrix.stream().map(matrix -> {
FacMatrixBySubProjectVo matrixVo = new FacMatrixBySubProjectVo();
matrixVo.setMatrixId(matrix.getId());
matrixVo.setName(matrix.getMatrixName());
return matrixVo;
}).toList());
}
return vo;
}).toList();
}
/**
* 查询当前登录用户项目列表以及项目列表下的分包公司列表
*
@ -520,7 +583,7 @@ public class BusProjectServiceImpl extends ServiceImpl<BusProjectMapper, BusProj
}
// 关联子项目
List<BusSubProjectVo> subProjectVoList = new ArrayList<>();
if (subProjectMap.containsKey(project.getId())){
if (subProjectMap.containsKey(project.getId())) {
subProjectVoList = subProjectMap.get(project.getId()).stream().map(subProject -> {
BusSubProjectVo subProjectVo = new BusSubProjectVo();
BeanUtils.copyProperties(subProject, subProjectVo);
@ -542,10 +605,10 @@ public class BusProjectServiceImpl extends ServiceImpl<BusProjectMapper, BusProj
*/
@Override
public void validAuth(Long projectId, Long userId) {
QueryWrapper<BusUserProjectRelevancy> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("project_id", projectId);
queryWrapper.eq("user_id", userId);
if (userProjectRelevancyService.count(queryWrapper) <= 0) {
LambdaQueryWrapper<BusUserProjectRelevancy> lqw = new LambdaQueryWrapper<>();
lqw.eq(BusUserProjectRelevancy::getProjectId, projectId);
lqw.eq(BusUserProjectRelevancy::getUserId, userId);
if (userProjectRelevancyService.count(lqw) <= 0) {
throw new ServiceException("当前用户无该项目权限操作", HttpStatus.FORBIDDEN);
}
}

View File

@ -0,0 +1,7 @@
<?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.dromara.other.mapper.OthDevicePresetMapper">
</mapper>

View File

@ -0,0 +1,7 @@
<?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.dromara.other.mapper.OthYs7DeviceMapper">
</mapper>