diff --git a/xinnengyuan/ruoyi-admin/src/main/resources/application.yml b/xinnengyuan/ruoyi-admin/src/main/resources/application.yml index 6938f01b..2f2a5f62 100644 --- a/xinnengyuan/ruoyi-admin/src/main/resources/application.yml +++ b/xinnengyuan/ruoyi-admin/src/main/resources/application.yml @@ -137,6 +137,7 @@ security: - /facility/matrix/** - /hat/device/data - /websocket/ue + - /websocket/vehicle # 多租户配置 tenant: diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/gps/controller/GpsEquipmentController.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/gps/controller/GpsEquipmentController.java index bc96bea6..3447d4b0 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/gps/controller/GpsEquipmentController.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/gps/controller/GpsEquipmentController.java @@ -92,6 +92,11 @@ public class GpsEquipmentController extends BaseController { return gpsEquipmentService.queryPageList(bo, pageQuery); } + /** + * 查询GPS设备详细列表给车辆 + * @param bo + * @return + */ @GetMapping("/getListToVehicle") public R> getListToVehicle(GpsEquipmentBo bo) { return R.ok(gpsEquipmentService.getListToVehicle(bo)); diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/gps/service/IGpsEquipmentSonService.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/gps/service/IGpsEquipmentSonService.java index ce672613..f7dc357c 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/gps/service/IGpsEquipmentSonService.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/gps/service/IGpsEquipmentSonService.java @@ -87,4 +87,5 @@ public interface IGpsEquipmentSonService extends IService{ List getUeUserListByProjectId(LocalDateTime startOfDay, LocalDateTime now); List getVehicleList(GpsEquipmentSonBo bo); + List getNewVehicleList(GpsEquipmentSonBo bo); } diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/gps/service/impl/GpsEquipmentServiceImpl.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/gps/service/impl/GpsEquipmentServiceImpl.java index 3db89308..d4e6ce78 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/gps/service/impl/GpsEquipmentServiceImpl.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/gps/service/impl/GpsEquipmentServiceImpl.java @@ -35,6 +35,7 @@ import org.dromara.project.domain.vo.project.BusProjectVo; import org.dromara.project.service.IBusProjectService; import org.dromara.system.domain.vo.SysUserVo; import org.dromara.system.service.ISysUserService; +import org.dromara.websocket.websocket.service.VehicleWebSocketServer; import org.redisson.api.DeletedObjectListener; import org.redisson.api.ExpiredObjectListener; import org.redisson.api.listener.SetObjectListener; @@ -263,7 +264,6 @@ public class GpsEquipmentServiceImpl extends ServiceImpl 0){ - if (equipment != null && StringUtils.isNotEmpty(equipment.getModelId())) { + if (equipment != null && StringUtils.isNotEmpty(equipment.getModelId())) { + int onlineCount = InitOnStartWebSocketServer.getOnlineCount(); + if (onlineCount > 0){ String ued = ueStructureJsonMessage(gpsEquipmentSon, equipment.getModelId()); InitOnStartWebSocketServer.sendToAll(ued); } } + //判断车辆轨迹是否有连接 + if (equipment != null && equipment.getClientType() == 1 && equipment.getUserId() != null) { + int onlineCount1 = VehicleWebSocketServer.getOnlineCount(); + if (onlineCount1 > 0) { + String vehicled = vehicleStructureJsonMessage(gpsEquipmentSon); + VehicleWebSocketServer.sendToSubscription(gpsEquipmentSon.getUserId()+"-"+gpsEquipmentSon.getTripId(), vehicled); + } + } + + + Set sessionsAll = WebSocketSessionHolder.getSessionsAll(); + if (!sessionsAll.isEmpty()) { String pushContent = buildPushMessage(gpsEquipmentSon); @@ -348,6 +360,19 @@ public class GpsEquipmentServiceImpl extends ServiceImpl getNewVehicleList(GpsEquipmentSonBo bo) { + return baseMapper.selectVoList(new LambdaQueryWrapper() + .eq(GpsEquipmentSon::getUserId,bo.getUserId()) + .eq(GpsEquipmentSon::getTripId,bo.getTripId()) + .orderByDesc(GpsEquipmentSon::getCreateTime)); + } } diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/vehicle/controller/VehVehicleInfoController.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/vehicle/controller/VehVehicleInfoController.java index 8b2d1fb0..f03d82d5 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/vehicle/controller/VehVehicleInfoController.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/vehicle/controller/VehVehicleInfoController.java @@ -17,6 +17,7 @@ import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.common.web.core.BaseController; import org.dromara.vehicle.domain.bo.VehVehicleInfoBo; import org.dromara.vehicle.domain.vo.VehVehicleInfoVo; +import org.dromara.vehicle.domain.vo.VehVehicleTripVo; import org.dromara.vehicle.service.IVehVehicleInfoService; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -45,6 +46,17 @@ public class VehVehicleInfoController extends BaseController { public TableDataInfo list(VehVehicleInfoBo bo, PageQuery pageQuery) { return vehVehicleInfoService.queryPageList(bo, pageQuery); } + /** + * 获取车辆行程信息 + * + * @param id 主键 + */ +// @SaCheckPermission("vehicle:vehicleInfo:query") + @GetMapping("/getTrip/{id}") + public R getTripInfo(@NotNull(message = "主键不能为空") + @PathVariable Long id) { + return R.ok(vehVehicleInfoService.getTripInfo(id)); + } /** * 查询车辆信息列表 diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/vehicle/service/IVehVehicleInfoService.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/vehicle/service/IVehVehicleInfoService.java index 08045e43..af987eff 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/vehicle/service/IVehVehicleInfoService.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/vehicle/service/IVehVehicleInfoService.java @@ -1,5 +1,6 @@ package org.dromara.vehicle.service; +import jakarta.validation.constraints.NotNull; import org.dromara.vehicle.domain.vo.VehVehicleInfoVo; import org.dromara.vehicle.domain.bo.VehVehicleInfoBo; import org.dromara.vehicle.domain.VehVehicleInfo; @@ -7,6 +8,8 @@ import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.common.mybatis.core.page.PageQuery; import com.baomidou.mybatisplus.extension.service.IService; +import org.dromara.vehicle.domain.vo.VehVehicleTripVo; + import java.util.Collection; import java.util.List; @@ -81,4 +84,6 @@ public interface IVehVehicleInfoService extends IService{ * @return */ int unBindClient(VehVehicleInfoBo bo); + + VehVehicleTripVo getTripInfo(Long id); } diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/vehicle/service/IVehVehicleTripService.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/vehicle/service/IVehVehicleTripService.java index 53981d4b..2323fc10 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/vehicle/service/IVehVehicleTripService.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/vehicle/service/IVehVehicleTripService.java @@ -107,4 +107,11 @@ public interface IVehVehicleTripService extends IService { * @return */ Long getTripId(Long id); + + /** + * 根据车辆id获取最新行程信息 + * @param id + * @return + */ + VehVehicleTripVo getTripInfoByVehicleId(Long id); } diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/vehicle/service/impl/VehVehicleInfoServiceImpl.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/vehicle/service/impl/VehVehicleInfoServiceImpl.java index bd097ea0..f60604ea 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/vehicle/service/impl/VehVehicleInfoServiceImpl.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/vehicle/service/impl/VehVehicleInfoServiceImpl.java @@ -18,9 +18,12 @@ import org.dromara.gps.service.IGpsEquipmentService; import org.dromara.gps.service.IGpsManmachineService; import org.dromara.vehicle.domain.VehVehicleInfo; import org.dromara.vehicle.domain.bo.VehVehicleInfoBo; +import org.dromara.vehicle.domain.enums.VehVehicleInfoStatusEnum; import org.dromara.vehicle.domain.vo.VehVehicleInfoVo; +import org.dromara.vehicle.domain.vo.VehVehicleTripVo; import org.dromara.vehicle.mapper.VehVehicleInfoMapper; import org.dromara.vehicle.service.IVehVehicleInfoService; +import org.dromara.vehicle.service.IVehVehicleTripService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; @@ -50,6 +53,10 @@ public class VehVehicleInfoServiceImpl extends ServiceImpl().set(VehVehicleInfo::getClientId,null).eq(VehVehicleInfo::getId,bo.getId())); } + + /** + * 通过车辆id获取车辆的当前行程信息 + * @param id + * @return + */ + @Override + public VehVehicleTripVo getTripInfo(Long id) { + VehVehicleInfoVo vehVehicleInfoVo = baseMapper.selectVoById(id); + if (vehVehicleInfoVo == null) { + throw new ServiceException("车辆信息为空"); + } + if (!VehVehicleInfoStatusEnum.IN_USE.getValue().equals(vehVehicleInfoVo.getVehicleStatus())){ + return null; + } + + return vehVehicleTripService.getTripInfoByVehicleId(id); + } } diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/vehicle/service/impl/VehVehicleTripServiceImpl.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/vehicle/service/impl/VehVehicleTripServiceImpl.java index 2bd88e11..40892118 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/vehicle/service/impl/VehVehicleTripServiceImpl.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/vehicle/service/impl/VehVehicleTripServiceImpl.java @@ -476,6 +476,14 @@ public class VehVehicleTripServiceImpl extends ServiceImpl() + .eq(VehVehicleTrip::getVehicleId, id) + .orderByDesc(VehVehicleTrip::getCreateTime) + .last("limit 1")); + } + /** * 构建用户行程及其对应申请的展示列表 * diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/websocket/websocket/domain/vo/VehicleVo.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/websocket/websocket/domain/vo/VehicleVo.java new file mode 100644 index 00000000..05ddc3cf --- /dev/null +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/websocket/websocket/domain/vo/VehicleVo.java @@ -0,0 +1,27 @@ +package org.dromara.websocket.websocket.domain.vo; + +import com.alibaba.excel.annotation.ExcelProperty; +import lombok.Data; +import org.dromara.common.excel.annotation.ExcelDictFormat; +import org.dromara.common.excel.convert.ExcelDictConvert; + +import java.math.BigDecimal; + +@Data +public class VehicleVo { + + /** + * 纬度(精确到6位小数) + */ + @ExcelProperty(value = "纬度", converter = ExcelDictConvert.class) + @ExcelDictFormat(readConverterExp = "精=确到6位小数") + private BigDecimal locLatitude; + + /** + * 经度(精确到6位小数) + */ + @ExcelProperty(value = "经度", converter = ExcelDictConvert.class) + @ExcelDictFormat(readConverterExp = "精=确到6位小数") + private BigDecimal locLongitude; + +} diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/websocket/websocket/service/VehicleWebSocketServer.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/websocket/websocket/service/VehicleWebSocketServer.java new file mode 100644 index 00000000..e3d00038 --- /dev/null +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/websocket/websocket/service/VehicleWebSocketServer.java @@ -0,0 +1,227 @@ +package org.dromara.websocket.websocket.service; + +import cn.hutool.json.JSONUtil; +import jakarta.websocket.*; +import jakarta.websocket.server.ServerEndpoint; +import lombok.extern.slf4j.Slf4j; +import org.dromara.bigscreen.service.ProjectBigScreenService; +import org.dromara.common.core.utils.SpringUtils; +import org.dromara.gps.domain.bo.GpsEquipmentSonBo; +import org.dromara.gps.domain.vo.GpsEquipmentSonVo; +import org.dromara.gps.service.IGpsEquipmentSonService; +import org.dromara.websocket.websocket.domain.vo.VehicleVo; +import org.springframework.stereotype.Component; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ConcurrentHashMap; + +/** + * 车辆轨迹 WebSocket 服务端(支持订阅消息) + * 端点路径:/websocket/vehicle + */ +@Slf4j +@ServerEndpoint("/websocket/vehicle") // 客户端连接时需携带订阅ID参数:ws://xxx/websocket/vehicle?subscriptionId=xxx +@Component +public class VehicleWebSocketServer { + + // 1. 存储所有在线会话(sessionId -> Session) + private static final Map ONLINE_SESSIONS = new ConcurrentHashMap<>(); + + // 2. 核心:订阅ID与会话的映射(subscriptionId -> Session) + private static final Map SUBSCRIPTION_SESSIONS = new ConcurrentHashMap<>(); + + // 3. 反向映射:会话ID与订阅ID的映射(用于断开连接时清理订阅关系) + private static final Map SESSION_TO_SUBSCRIPTION = new ConcurrentHashMap<>(); + + // 当前会话对应的订阅ID(每个连接实例的专属变量) + private String currentSubscriptionId; + + + static { + log.info("✅ 车辆轨迹 WebSocket 服务端已随项目启动初始化!端点路径:/websocket/vehicle"); + } + + /** + * 客户端连接时触发(解析订阅ID并建立映射关系) + */ + @OnOpen + public void onOpen(Session session) { + // 从连接URL的查询参数中获取订阅ID(客户端连接格式:ws://xxx/websocket/vehicle?subscriptionId=123) + Map> params = session.getRequestParameterMap(); + List subscriptionIds = params.get("subscriptionId"); + if (subscriptionIds != null && !subscriptionIds.isEmpty()) { + this.currentSubscriptionId = subscriptionIds.get(0); // 取第一个订阅ID + // 建立映射关系 + SUBSCRIPTION_SESSIONS.put(currentSubscriptionId, session); + SESSION_TO_SUBSCRIPTION.put(session.getId(), currentSubscriptionId); + log.info("📌 客户端订阅成功!订阅ID:{},会话ID:{},当前订阅数:{}", + currentSubscriptionId, session.getId(), SUBSCRIPTION_SESSIONS.size()); + } else { + log.warn("📌 客户端连接未携带订阅ID!会话ID:{}", session.getId()); + } + + // 存储会话到在线列表 + ONLINE_SESSIONS.put(session.getId(), session); + log.info("📌 客户端连接成功!会话ID:{},当前在线数:{}", session.getId(), ONLINE_SESSIONS.size()); + + // 异步推送初始化数据(原有逻辑保留) + CompletableFuture.runAsync(() -> { + try { + String[] split = currentSubscriptionId.split("-"); + IGpsEquipmentSonService service = SpringUtils.getBean(IGpsEquipmentSonService.class); + GpsEquipmentSonBo bo = new GpsEquipmentSonBo(); + bo.setUserId(Long.parseLong(split[0])); + bo.setTripId(Long.parseLong(split[1])); + List list = service.getNewVehicleList(bo); + if (list == null || list.isEmpty()) { + session.getBasicRemote().sendText("初始化数据为空"); + log.warn("会话[{}]未获取到初始化数据", session.getId()); + return; + } + List vehicleVos = new ArrayList<>(); + for (GpsEquipmentSonVo ueClient : list) { + VehicleVo vo = new VehicleVo(); + vo.setLocLatitude(ueClient.getLocLatitude()); + vo.setLocLongitude(ueClient.getLocLongitude()); + vehicleVos.add(vo); + } + session.getBasicRemote().sendText(JSONUtil.toJsonStr(vehicleVos)); + log.info("📤 已向会话[{}]推送初始化数据,长度:{}字节", session.getId(), vehicleVos.size()); + } catch (Exception e) { + log.error("会话[{}]初始化数据处理失败", session.getId(), e); + try { + if (session.isOpen()) { + session.getBasicRemote().sendText("初始化失败:" + e.getMessage()); + } + } catch (IOException ex) { + log.error("会话[{}]推送错误信息失败", session.getId(), ex); + } + } + }); + } + + /** + * 接收客户端消息 + */ + @OnMessage + public void onMessage(String message, Session session) { + log.info("📥 收到会话[{}](订阅ID:{})消息:{}", session.getId(), currentSubscriptionId, message); + // 可选:回复客户端 + try { + session.getBasicRemote().sendText("服务端已收到消息:" + message); + } catch (IOException e) { + log.error("📤 回复会话[{}]失败:{}", session.getId(), e.getMessage()); + } + } + + /** + * 客户端断开连接(清理订阅关系) + */ + @OnClose + public void onClose(Session session, CloseReason reason) { + // 1. 移除在线会话 + ONLINE_SESSIONS.remove(session.getId()); + // 2. 清理订阅关系 + String subscriptionId = SESSION_TO_SUBSCRIPTION.get(session.getId()); + if (subscriptionId != null) { + SUBSCRIPTION_SESSIONS.remove(subscriptionId); + SESSION_TO_SUBSCRIPTION.remove(session.getId()); + log.info("🔌 客户端订阅关系已清除!订阅ID:{},会话ID:{}", subscriptionId, session.getId()); + } + log.info("🔌 客户端断开连接!会话ID:{},原因:{},当前在线数:{},当前订阅数:{}", + session.getId(), reason.getReasonPhrase(), + ONLINE_SESSIONS.size(), SUBSCRIPTION_SESSIONS.size()); + } + + /** + * 连接异常 + */ + @OnError + public void onError(Session session, Throwable error) { + log.error("⚠️ 会话[{}](订阅ID:{})异常:{}", session.getId(), currentSubscriptionId, error.getMessage(), error); + } + + + // ------------------------------ 订阅消息发送工具方法(供外部调用) ------------------------------ + + /** + * 向指定订阅ID的客户端发送消息 + * @param subscriptionId 订阅ID + * @param message 消息内容 + * @return 是否发送成功 + */ + public static boolean sendToSubscription(String subscriptionId, String message) { + if (subscriptionId == null || message == null) { + log.warn("⚠️ 订阅ID或消息为空,发送失败"); + return false; + } + // 从订阅映射中获取目标会话 + Session session = SUBSCRIPTION_SESSIONS.get(subscriptionId); + if (session == null || !session.isOpen()) { + log.warn("⚠️ 订阅ID[{}]对应的客户端未连接或已断开", subscriptionId); + return false; + } + // 发送消息 + try { + session.getBasicRemote().sendText(message); + log.info("📤 已向订阅ID[{}]发送消息:{}", subscriptionId, message); + return true; + } catch (IOException e) { + log.error("📤 向订阅ID[{}]发送消息失败", subscriptionId, e); + return false; + } + } + + /** + * 向所有订阅客户端广播消息 + * @param message 消息内容 + */ + public static void broadcastToAllSubscriptions(String message) { + if (SUBSCRIPTION_SESSIONS.isEmpty()) { + log.warn("⚠️ 无订阅客户端,无需广播消息"); + return; + } + SUBSCRIPTION_SESSIONS.forEach((subscriptionId, session) -> { + if (session.isOpen()) { + try { + session.getBasicRemote().sendText(message); + log.info("📤 已向订阅ID[{}]广播消息", subscriptionId); + } catch (IOException e) { + log.error("📤 向订阅ID[{}]广播消息失败", subscriptionId, e); + } + } + }); + } + + /** + * 获取当前订阅数 + */ + public static int getSubscriptionCount() { + return SUBSCRIPTION_SESSIONS.size(); + } + + // 原有工具方法保留 + public static void sendToAll(String message) { + if (ONLINE_SESSIONS.isEmpty()) { + log.warn("⚠️ 无在线客户端,无需发送消息"); + return; + } + ONLINE_SESSIONS.values().forEach(session -> { + if (session.isOpen()) { + try { + session.getBasicRemote().sendText(message); + } catch (IOException e) { + log.error("📤 向会话[{}]发送消息失败:{}", session.getId(), e.getMessage()); + } + } + }); + } + + public static int getOnlineCount() { + return ONLINE_SESSIONS.size(); + } +} diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/xzd/comprehensive/controller/XzdCsContractInformationController.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/xzd/comprehensive/controller/XzdCsContractInformationController.java index 32fb51b2..104d792d 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/xzd/comprehensive/controller/XzdCsContractInformationController.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/xzd/comprehensive/controller/XzdCsContractInformationController.java @@ -15,7 +15,9 @@ import org.dromara.xzd.comprehensive.service.IXzdCsContractChangeService; import org.dromara.xzd.comprehensive.service.IXzdCsContractSuspendService; import org.dromara.xzd.domain.bo.XzdBusinessSealBo; import org.dromara.xzd.domain.vo.XzdBusinessSealVo; +import org.dromara.xzd.domain.vo.XzdProjectVo; import org.dromara.xzd.service.IXzdBusinessSealService; +import org.dromara.xzd.service.IXzdProjectService; import org.springframework.context.annotation.Lazy; import org.springframework.web.bind.annotation.*; import org.springframework.validation.annotation.Validated; @@ -55,6 +57,23 @@ public class XzdCsContractInformationController extends BaseController { @Lazy private final IXzdCsContractChangeService xzdCsContractChangeService; + @Lazy + private final IXzdProjectService xzdProjectService; + + + + /** + * 获取项目信息详细信息 + * + * @param id 主键 + */ + @SaCheckPermission(value = {"comprehensive:csContractInformation:add","comprehensive:csContractInformation:edit","comprehensive:csContractInformation:list"},mode = SaMode.OR) + @GetMapping("/getProject/{id}") + public R getProjectInfo(@NotNull(message = "主键不能为空") + @PathVariable Long id) { + return R.ok(xzdProjectService.queryById(id)); + } + /** * 查询综合服务合同变更列表