From 2a2fd21bdb50fd7a9395e026e1bb61f8e68afe2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=89=E4=B8=99?= <10604541+sanbing-os@user.noreply.gitee.com> Date: Sat, 27 Sep 2025 19:01:50 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=88=B7=E6=96=B0=E6=8C=89?= =?UTF-8?q?=E9=92=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/adapter/controller/GunController.java | 2 +- .../adapter/controller/PileController.java | 2 +- .../app/adapter/controller/RpcController.java | 4 +- .../jcpp/app/adapter/dto/RestartPileDTO.java | 2 +- .../jcpp/app/adapter/dto/SetPricingDTO.java | 2 +- .../jcpp/app/adapter/dto/StartChargeDTO.java | 2 +- .../jcpp/app/adapter/dto/StopChargeDTO.java | 2 +- .../jcpp/app/adapter/dto/TimeSyncDTO.java | 2 +- .../jcpp/app/adapter/request/RpcRequest.java | 2 +- .../app/service/impl/DefaultGunService.java | 2 +- .../impl/DefaultPileProtocolService.java | 2 +- .../src/main/resources/mapper/GunMapper.xml | 8 +- .../src/main/resources/mapper/PileMapper.xml | 4 +- .../v340/cmd/LvnengV340HeartbeatULCmd.java | 2 +- .../v340/cmd/LvnengV340RealTimeDataULCmd.java | 2 +- .../YunKuaiChongV150RealTimeDataULCmd.java | 6 + jcpp-web-ui/src/components/GunDebug.tsx | 123 +++++++++++++++--- jcpp-web-ui/src/components/GunManagement.tsx | 45 +++++-- jcpp-web-ui/src/components/PileManagement.tsx | 47 ++++--- .../src/components/StationManagement.tsx | 45 +++++-- 20 files changed, 226 insertions(+), 80 deletions(-) diff --git a/jcpp-app/src/main/java/sanbing/jcpp/app/adapter/controller/GunController.java b/jcpp-app/src/main/java/sanbing/jcpp/app/adapter/controller/GunController.java index 5afea43..45c007e 100644 --- a/jcpp-app/src/main/java/sanbing/jcpp/app/adapter/controller/GunController.java +++ b/jcpp-app/src/main/java/sanbing/jcpp/app/adapter/controller/GunController.java @@ -82,7 +82,7 @@ public class GunController extends BaseController { // 通过AttributeService获取充电枪运行状态 ListenableFuture> attributeFuture = attributeService.find(gun.getId(), AttrKeyEnum.GUN_RUN_STATUS.getCode()); - + Optional attributeResult = attributeFuture.get(); String status = null; if (attributeResult.isPresent()) { diff --git a/jcpp-app/src/main/java/sanbing/jcpp/app/adapter/controller/PileController.java b/jcpp-app/src/main/java/sanbing/jcpp/app/adapter/controller/PileController.java index af14c2c..0d6d0c9 100644 --- a/jcpp-app/src/main/java/sanbing/jcpp/app/adapter/controller/PileController.java +++ b/jcpp-app/src/main/java/sanbing/jcpp/app/adapter/controller/PileController.java @@ -94,7 +94,7 @@ public class PileController extends BaseController { // 通过AttributeService获取充电桩状态 ListenableFuture> attributeFuture = attributeService.find(pile.getId(), AttrKeyEnum.STATUS.getCode()); - + Optional attributeResult = attributeFuture.get(); String status = null; if (attributeResult.isPresent()) { diff --git a/jcpp-app/src/main/java/sanbing/jcpp/app/adapter/controller/RpcController.java b/jcpp-app/src/main/java/sanbing/jcpp/app/adapter/controller/RpcController.java index cd47e96..4246ce9 100644 --- a/jcpp-app/src/main/java/sanbing/jcpp/app/adapter/controller/RpcController.java +++ b/jcpp-app/src/main/java/sanbing/jcpp/app/adapter/controller/RpcController.java @@ -23,7 +23,7 @@ import sanbing.jcpp.proto.gen.DownlinkProto.*; /** * RPC控制器 - 通用化的充电桩下行指令接口 - * + * * @author 九筒 */ @RestController @@ -156,7 +156,7 @@ public class RpcController extends BaseController { /** * 处理离线卡余额更新指令 */ - private void handleOfflineCardBalanceUpdate(JsonNode parameter) { + private void handleOfflineCardBalanceUpdate(JsonNode parameter) throws Exception { OfflineCardBalanceUpdateRequest request = JacksonUtil.fromJson(parameter, OfflineCardBalanceUpdateRequest.class); pileProtocolService.offlineCardBalanceUpdateRequest(request); } diff --git a/jcpp-app/src/main/java/sanbing/jcpp/app/adapter/dto/RestartPileDTO.java b/jcpp-app/src/main/java/sanbing/jcpp/app/adapter/dto/RestartPileDTO.java index 092cea9..636ab04 100644 --- a/jcpp-app/src/main/java/sanbing/jcpp/app/adapter/dto/RestartPileDTO.java +++ b/jcpp-app/src/main/java/sanbing/jcpp/app/adapter/dto/RestartPileDTO.java @@ -12,7 +12,7 @@ import lombok.Data; /** * 重启充电桩DTO - * + * * @author 九筒 */ @Data diff --git a/jcpp-app/src/main/java/sanbing/jcpp/app/adapter/dto/SetPricingDTO.java b/jcpp-app/src/main/java/sanbing/jcpp/app/adapter/dto/SetPricingDTO.java index 85036cf..eaae698 100644 --- a/jcpp-app/src/main/java/sanbing/jcpp/app/adapter/dto/SetPricingDTO.java +++ b/jcpp-app/src/main/java/sanbing/jcpp/app/adapter/dto/SetPricingDTO.java @@ -13,7 +13,7 @@ import sanbing.jcpp.proto.gen.DownlinkProto.SetPricingRequest; /** * 设置计费策略DTO - * + * * @author 九筒 */ @Data diff --git a/jcpp-app/src/main/java/sanbing/jcpp/app/adapter/dto/StartChargeDTO.java b/jcpp-app/src/main/java/sanbing/jcpp/app/adapter/dto/StartChargeDTO.java index 74dc36b..60a63a9 100644 --- a/jcpp-app/src/main/java/sanbing/jcpp/app/adapter/dto/StartChargeDTO.java +++ b/jcpp-app/src/main/java/sanbing/jcpp/app/adapter/dto/StartChargeDTO.java @@ -14,7 +14,7 @@ import java.math.BigDecimal; /** * 启动充电DTO - * + * * @author 九筒 */ @Data diff --git a/jcpp-app/src/main/java/sanbing/jcpp/app/adapter/dto/StopChargeDTO.java b/jcpp-app/src/main/java/sanbing/jcpp/app/adapter/dto/StopChargeDTO.java index 5bb9830..5bbed04 100644 --- a/jcpp-app/src/main/java/sanbing/jcpp/app/adapter/dto/StopChargeDTO.java +++ b/jcpp-app/src/main/java/sanbing/jcpp/app/adapter/dto/StopChargeDTO.java @@ -11,7 +11,7 @@ import lombok.Data; /** * 停止充电DTO - * + * * @author 九筒 */ @Data diff --git a/jcpp-app/src/main/java/sanbing/jcpp/app/adapter/dto/TimeSyncDTO.java b/jcpp-app/src/main/java/sanbing/jcpp/app/adapter/dto/TimeSyncDTO.java index b1750a5..eb4c7d3 100644 --- a/jcpp-app/src/main/java/sanbing/jcpp/app/adapter/dto/TimeSyncDTO.java +++ b/jcpp-app/src/main/java/sanbing/jcpp/app/adapter/dto/TimeSyncDTO.java @@ -14,7 +14,7 @@ import java.time.LocalDateTime; /** * 时间同步DTO - * + * * @author 九筒 */ @Data diff --git a/jcpp-app/src/main/java/sanbing/jcpp/app/adapter/request/RpcRequest.java b/jcpp-app/src/main/java/sanbing/jcpp/app/adapter/request/RpcRequest.java index 52476b1..07a4994 100644 --- a/jcpp-app/src/main/java/sanbing/jcpp/app/adapter/request/RpcRequest.java +++ b/jcpp-app/src/main/java/sanbing/jcpp/app/adapter/request/RpcRequest.java @@ -13,7 +13,7 @@ import lombok.Data; /** * RPC请求参数 - * + * * @author 九筒 */ @Data diff --git a/jcpp-app/src/main/java/sanbing/jcpp/app/service/impl/DefaultGunService.java b/jcpp-app/src/main/java/sanbing/jcpp/app/service/impl/DefaultGunService.java index 91ab343..ba43d1b 100644 --- a/jcpp-app/src/main/java/sanbing/jcpp/app/service/impl/DefaultGunService.java +++ b/jcpp-app/src/main/java/sanbing/jcpp/app/service/impl/DefaultGunService.java @@ -198,7 +198,7 @@ public class DefaultGunService implements GunService { // 保存充电枪状态到属性表 saveGunStatusChange(gun.getId(), dbStatus.name(), ts); - log.info("充电枪状态更新成功: 桩编码={}, 枪编号={}, 原状态={}, 新状态={}", + log.info("充电枪状态更新成功: 桩编码={}, 枪编号={}, 原状态={}, 新状态={}", pileCode, gunNo, currentStatus, dbStatus); // 根据充电枪状态判断是否需要更新充电桩状态 diff --git a/jcpp-app/src/main/java/sanbing/jcpp/app/service/impl/DefaultPileProtocolService.java b/jcpp-app/src/main/java/sanbing/jcpp/app/service/impl/DefaultPileProtocolService.java index ce7a99b..f96db59 100644 --- a/jcpp-app/src/main/java/sanbing/jcpp/app/service/impl/DefaultPileProtocolService.java +++ b/jcpp-app/src/main/java/sanbing/jcpp/app/service/impl/DefaultPileProtocolService.java @@ -630,7 +630,7 @@ public class DefaultPileProtocolService implements PileProtocolService { String additionalInfo = bmsHandshakeProto.getAdditionalInfo(); log.info("BMS充电握手信息: 交易流水号: {}, 桩编码: {}, 枪号: {}, 车辆VIN: {}, BMS协议版本: {}, " + - "电池类型: {}, 电池容量: {}Ah, 附加信息: {}", + "电池类型: {}, 电池容量: {}Ah, 附加信息: {}", tradeNo, pileCode, gunNo, carVinCode, bmsProtocolVersion, bmsBatteryType, bmsPowerCapacity, additionalInfo); diff --git a/jcpp-app/src/main/resources/mapper/GunMapper.xml b/jcpp-app/src/main/resources/mapper/GunMapper.xml index c09164b..656a128 100644 --- a/jcpp-app/src/main/resources/mapper/GunMapper.xml +++ b/jcpp-app/src/main/resources/mapper/GunMapper.xml @@ -101,8 +101,8 @@ @@ -139,8 +139,8 @@ a_run_status.str_v as run_status - FROM t_gun g - + FROM t_gun g + LEFT JOIN t_station s ON g.station_id = s.id diff --git a/jcpp-app/src/main/resources/mapper/PileMapper.xml b/jcpp-app/src/main/resources/mapper/PileMapper.xml index 560d7bf..526a041 100644 --- a/jcpp-app/src/main/resources/mapper/PileMapper.xml +++ b/jcpp-app/src/main/resources/mapper/PileMapper.xml @@ -36,9 +36,9 @@ COALESCE(g.gun_count, 0) as gun_count - - FROM t_pile p + FROM t_pile p + LEFT JOIN t_attr a ON ( a.entity_id = p.id AND diff --git a/jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/v340/cmd/LvnengV340HeartbeatULCmd.java b/jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/v340/cmd/LvnengV340HeartbeatULCmd.java index cd9ffe8..77dfe5b 100644 --- a/jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/v340/cmd/LvnengV340HeartbeatULCmd.java +++ b/jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/v340/cmd/LvnengV340HeartbeatULCmd.java @@ -54,7 +54,7 @@ public class LvnengV340HeartbeatULCmd extends LvnengUplinkCmdExe { //5预留 byteBuf.skipBytes(16); - + // 会话添加充电桩编码 tcpSession.addPileCode(pileCode); // 注册前置会话 diff --git a/jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/v340/cmd/LvnengV340RealTimeDataULCmd.java b/jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/v340/cmd/LvnengV340RealTimeDataULCmd.java index 3a534f1..53449fb 100644 --- a/jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/v340/cmd/LvnengV340RealTimeDataULCmd.java +++ b/jcpp-protocol-lvneng/src/main/java/sanbing/jcpp/protocol/lvneng/v340/cmd/LvnengV340RealTimeDataULCmd.java @@ -219,7 +219,7 @@ public class LvnengV340RealTimeDataULCmd extends LvnengUplinkCmdExe { //46 预留 1 byteBuf.skipBytes(1); - + // 会话添加充电桩编码 tcpSession.addPileCode(pileCode); // 注册前置会话 diff --git a/jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/v150/cmd/YunKuaiChongV150RealTimeDataULCmd.java b/jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/v150/cmd/YunKuaiChongV150RealTimeDataULCmd.java index bf924ab..5951faa 100644 --- a/jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/v150/cmd/YunKuaiChongV150RealTimeDataULCmd.java +++ b/jcpp-protocol-yunkuaichong/src/main/java/sanbing/jcpp/protocol/yunkuaichong/v150/cmd/YunKuaiChongV150RealTimeDataULCmd.java @@ -140,6 +140,12 @@ public class YunKuaiChongV150RealTimeDataULCmd extends YunKuaiChongUplinkCmdExe .addAllFaultMessages(faults) .setAdditionalInfo(additionalInfo.toString()); + // 会话添加充电桩编码 + tcpSession.addPileCode(pileCode); + + // 注册前置会话 + ctx.getProtocolSessionRegistryProvider().register(tcpSession); + // 转发到后端 UplinkQueueMessage gunRunStatusMessage = uplinkMessageBuilder(pileCode, tcpSession, yunKuaiChongUplinkMessage) .setGunRunStatusProto(gunRunStatusProtoBuilder) diff --git a/jcpp-web-ui/src/components/GunDebug.tsx b/jcpp-web-ui/src/components/GunDebug.tsx index b6245a9..6de2619 100644 --- a/jcpp-web-ui/src/components/GunDebug.tsx +++ b/jcpp-web-ui/src/components/GunDebug.tsx @@ -7,7 +7,7 @@ import React, {useEffect, useState} from 'react'; import {useNavigate, useParams, useSearchParams} from 'react-router-dom'; import {Alert, Breadcrumb, Button, Card, Descriptions, Divider, message, Space, Spin, Typography} from 'antd'; -import {ArrowLeftOutlined, BugOutlined, HomeOutlined, PlayCircleOutlined} from '@ant-design/icons'; +import {ArrowLeftOutlined, BugOutlined, CopyOutlined, HomeOutlined, PlayCircleOutlined} from '@ant-design/icons'; import {Gun} from '../types'; import * as gunService from '../services/gunService'; import {api, getErrorMessage} from '../services/api'; @@ -91,6 +91,47 @@ const GunDebug: React.FC = () => { navigate(returnUrl); }; + // 获取完整的请求头信息(类似Swagger) + const getCompleteHeaders = () => { + const token = localStorage.getItem('token'); + const headers: Record = { + 'Accept': 'application/json;charset=UTF-8', + 'Content-Type': 'application/json;charset=UTF-8', + }; + + if (token) { + headers['Authorization'] = `Bearer ${token}`; + } + + return headers; + }; + + // 生成curl命令(类似Swagger UI) + const generateCurlCommand = (url: string, method: string, headers: Record, requestBody: any) => { + let curlCommand = `curl -X ${method} "${url}"`; + + // 添加请求头 + Object.entries(headers).forEach(([key, value]) => { + curlCommand += ` \\\n -H "${key}: ${value}"`; + }); + + // 添加请求体(如果有) + if (requestBody && method !== 'GET') { + curlCommand += ` \\\n -d '${JSON.stringify(requestBody)}'`; + } + + return curlCommand; + }; + + // 复制curl命令到剪贴板 + const copyCurlCommand = (curlCommand: string) => { + navigator.clipboard.writeText(curlCommand).then(() => { + message.success('cURL命令已复制到剪贴板'); + }).catch(() => { + message.error('复制失败,请手动复制'); + }); + }; + // 执行充电枪状态查询调试 const handleDebugGunStatus = async () => { if (!gun) return; @@ -98,16 +139,16 @@ const GunDebug: React.FC = () => { // 清除充电桩调试结果,只显示充电枪调试结果 setPileDebugResult(null); setDebugLoading(true); - try { - const headers = { - 'Content-Type': 'application/json', - }; + const fullUrl = `${api.defaults.baseURL}/api/guns/status/${gun.gunCode}`; + const headers = getCompleteHeaders(); + + try { // 直接调用现有的正确API接口 const response = await api.get(`/api/guns/status/${gun.gunCode}`); setDebugResult({ - url: `/api/guns/status/${gun.gunCode}`, + url: fullUrl, method: 'GET', headers, requestBody: null, @@ -123,9 +164,9 @@ const GunDebug: React.FC = () => { } } catch (error: any) { const errorResult = { - url: `/api/guns/status/${gun.gunCode}`, + url: fullUrl, method: 'GET', - headers: {'Content-Type': 'application/json'}, + headers, requestBody: null, response: {success: false, message: getErrorMessage(error)}, timestamp: new Date().toLocaleString(), @@ -149,16 +190,16 @@ const GunDebug: React.FC = () => { // 清除充电枪调试结果,只显示充电桩调试结果 setDebugResult(null); setPileDebugLoading(true); - try { - const headers = { - 'Content-Type': 'application/json', - }; + const fullUrl = `${api.defaults.baseURL}/api/piles/status/${gun.pileCode}`; + const headers = getCompleteHeaders(); + + try { // 直接调用现有的正确API接口 const response = await api.get(`/api/piles/status/${gun.pileCode}`); setPileDebugResult({ - url: `/api/piles/status/${gun.pileCode}`, + url: fullUrl, method: 'GET', headers, requestBody: null, @@ -174,9 +215,9 @@ const GunDebug: React.FC = () => { } } catch (error: any) { const errorResult = { - url: `/api/piles/status/${gun.pileCode}`, + url: fullUrl, method: 'GET', - headers: {'Content-Type': 'application/json'}, + headers, requestBody: null, response: {success: false, message: getErrorMessage(error)}, timestamp: new Date().toLocaleString(), @@ -302,6 +343,30 @@ const GunDebug: React.FC = () => { + + cURL 命令 + + +
+              {generateCurlCommand(debugResult.url, debugResult.method, debugResult.headers, debugResult.requestBody)}
+            
+ 请求头 (Headers)
 {
                             fontSize: 12,
                             overflow: 'auto'
                         }}>
-              {JSON.stringify(debugResult.requestBody, null, 2)}
+              {debugResult.requestBody ? JSON.stringify(debugResult.requestBody, null, 2) : 'null'}
             
响应结果 (Response) @@ -361,6 +426,30 @@ const GunDebug: React.FC = () => { + + cURL 命令 + + +
+              {generateCurlCommand(pileDebugResult.url, pileDebugResult.method, pileDebugResult.headers, pileDebugResult.requestBody)}
+            
+ 请求头 (Headers)
 {
                             fontSize: 12,
                             overflow: 'auto'
                         }}>
-              {JSON.stringify(pileDebugResult.requestBody, null, 2)}
+              {pileDebugResult.requestBody ? JSON.stringify(pileDebugResult.requestBody, null, 2) : 'null'}
             
响应结果 (Response) diff --git a/jcpp-web-ui/src/components/GunManagement.tsx b/jcpp-web-ui/src/components/GunManagement.tsx index 61ffd38..fd047d3 100644 --- a/jcpp-web-ui/src/components/GunManagement.tsx +++ b/jcpp-web-ui/src/components/GunManagement.tsx @@ -597,6 +597,13 @@ const GunManagement: React.FC = () => { updateSearchParams(newParams); }; + // 刷新数据 + const handleRefresh = () => { + // 使用当前的搜索参数重新加载数据 + updateSearchParams({...searchParams}); + setSelectedRowKeys([]); + }; + // 显示新建模态框 const showCreateModal = () => { setIsEdit(false); @@ -942,20 +949,30 @@ const GunManagement: React.FC = () => { -