20260126:模型排序&高德地图
This commit is contained in:
parent
652a32b797
commit
b770da12e3
@ -102,7 +102,7 @@ spring:
|
|||||||
redis:
|
redis:
|
||||||
host: localhost # 地址
|
host: localhost # 地址
|
||||||
port: 6379 # 端口,默认为6379
|
port: 6379 # 端口,默认为6379
|
||||||
database: 3 # 数据库索引
|
database: 0 # 数据库索引
|
||||||
password: fastbee # 密码
|
password: fastbee # 密码
|
||||||
timeout: 10s # 连接超时时间
|
timeout: 10s # 连接超时时间
|
||||||
lettuce:
|
lettuce:
|
||||||
|
|||||||
@ -50,8 +50,11 @@ public class TCPBootStrap {
|
|||||||
.setPort(port)
|
.setPort(port)
|
||||||
//设置报文最大长度 modbus-rtu
|
//设置报文最大长度 modbus-rtu
|
||||||
.setMaxFrameLength(1024)
|
.setMaxFrameLength(1024)
|
||||||
// 此处就是ASCII和注册包粘包了,无需strip掉 “分隔符” 即可
|
/*
|
||||||
.setDelimiters(new Delimiter(new byte[]{0x7e}, false))
|
* 此处就是ASCII和注册包粘包了,无需strip掉 “分隔符” 即可
|
||||||
|
* 最原始.setDelimiters(new Delimiter(new byte[]{0x7e}, true))
|
||||||
|
*/
|
||||||
|
.setDelimiters(new Delimiter(new byte[]{0x0A}, true))
|
||||||
.setDecoder(messageAdapter)
|
.setDecoder(messageAdapter)
|
||||||
.setEncoder(messageAdapter)
|
.setEncoder(messageAdapter)
|
||||||
.setHandlerMapping(handlerMapping)
|
.setHandlerMapping(handlerMapping)
|
||||||
|
|||||||
@ -125,13 +125,12 @@ public class DelimiterBasedFrameDecoder extends ByteToMessageDecoder {
|
|||||||
if (minDelim != null) {
|
if (minDelim != null) {
|
||||||
int minDelimLength = minDelim.value.length;
|
int minDelimLength = minDelim.value.length;
|
||||||
ByteBuf frame = null;
|
ByteBuf frame = null;
|
||||||
boolean keepDelimiterForNextFrame = shouldKeepDelimiterForNextFrame(minDelim) && minFrameLength > 0;
|
|
||||||
|
|
||||||
if (discardingTooLongFrame) {
|
if (discardingTooLongFrame) {
|
||||||
// 如果true,将长度不符合报文丢弃
|
// 如果true,将长度不符合报文丢弃
|
||||||
// 初始化原来的值
|
// 初始化原来的值
|
||||||
discardingTooLongFrame = false;
|
discardingTooLongFrame = false;
|
||||||
buffer.skipBytes(minFrameLength + (keepDelimiterForNextFrame ? 0 : minDelimLength));
|
buffer.skipBytes(minFrameLength + minDelimLength);
|
||||||
|
|
||||||
int tooLongFrameLength = this.tooLongFrameLength;
|
int tooLongFrameLength = this.tooLongFrameLength;
|
||||||
this.tooLongFrameLength = 0;
|
this.tooLongFrameLength = 0;
|
||||||
@ -143,16 +142,10 @@ public class DelimiterBasedFrameDecoder extends ByteToMessageDecoder {
|
|||||||
/*小于最小长度帧处理*/
|
/*小于最小长度帧处理*/
|
||||||
if (minFrameLength > maxFrameLength) {
|
if (minFrameLength > maxFrameLength) {
|
||||||
//放弃读取帧
|
//放弃读取帧
|
||||||
buffer.skipBytes(minFrameLength + (keepDelimiterForNextFrame ? 0 : minDelimLength));
|
buffer.skipBytes(minFrameLength + minDelimLength);
|
||||||
fail(minFrameLength);
|
fail(minFrameLength);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (keepDelimiterForNextFrame) {
|
|
||||||
frame = buffer.readRetainedSlice(minFrameLength);
|
|
||||||
return frame;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*是否需要跳过某字节*/
|
/*是否需要跳过某字节*/
|
||||||
if (minDelim.strip) {
|
if (minDelim.strip) {
|
||||||
//忽略长度等于0的报文
|
//忽略长度等于0的报文
|
||||||
@ -273,9 +266,6 @@ public class DelimiterBasedFrameDecoder extends ByteToMessageDecoder {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Modbus RTU:为了避免把请求帧(常见固定8字节)误当响应帧(第3字节是byteCount)导致截断,
|
|
||||||
// 这里采用"候选长度 + CRC校验"方式确定帧边界,兼容:请求/回显/响应/异常响应。
|
|
||||||
|
|
||||||
// 异常响应:地址(1) + 功能码(1|0x80) + 异常码(1) + CRC(2) = 5字节
|
// 异常响应:地址(1) + 功能码(1|0x80) + 异常码(1) + CRC(2) = 5字节
|
||||||
if ((functionCode & 0x80) != 0) {
|
if ((functionCode & 0x80) != 0) {
|
||||||
int len = 5;
|
int len = 5;
|
||||||
@ -309,8 +299,7 @@ public class DelimiterBasedFrameDecoder extends ByteToMessageDecoder {
|
|||||||
}
|
}
|
||||||
int byteCount = buffer.getByte(readerIndex + 2) & 0xFF;
|
int byteCount = buffer.getByte(readerIndex + 2) & 0xFF;
|
||||||
int respLen = 3 + byteCount + 2;
|
int respLen = 3 + byteCount + 2;
|
||||||
log.debug("[{}] Modbus功能码{}: byteCount={}, 预期帧长={}, 可读={}",
|
log.debug("[{}] Modbus功能码{}: byteCount={}, 预期帧长={}, 可读={}", deviceId, String.format("%02X", functionCode), byteCount, respLen, readable);
|
||||||
deviceId, String.format("%02X", functionCode), byteCount, respLen, readable);
|
|
||||||
if (respLen > maxFrameLength) {
|
if (respLen > maxFrameLength) {
|
||||||
log.warn("[{}] Modbus帧长度{}超过最大限制{}", deviceId, respLen, maxFrameLength);
|
log.warn("[{}] Modbus帧长度{}超过最大限制{}", deviceId, respLen, maxFrameLength);
|
||||||
return -1;
|
return -1;
|
||||||
@ -368,13 +357,7 @@ public class DelimiterBasedFrameDecoder extends ByteToMessageDecoder {
|
|||||||
byte[] crc = CRC16Utils.getCrc16Byte(data); // [low, high]
|
byte[] crc = CRC16Utils.getCrc16Byte(data); // [low, high]
|
||||||
int crcLo = buffer.getByte(offset + len - 2) & 0xFF;
|
int crcLo = buffer.getByte(offset + len - 2) & 0xFF;
|
||||||
int crcHi = buffer.getByte(offset + len - 1) & 0xFF;
|
int crcHi = buffer.getByte(offset + len - 1) & 0xFF;
|
||||||
boolean valid = ((crc[0] & 0xFF) == crcLo) && ((crc[1] & 0xFF) == crcHi);
|
return ((crc[0] & 0xFF) == crcLo) && ((crc[1] & 0xFF) == crcHi);
|
||||||
if (!valid && log.isDebugEnabled()) {
|
|
||||||
log.debug("[{}] CRC校验: 计算值={}{}, 实际值={}{}", deviceId,
|
|
||||||
String.format("%02X", crc[0] & 0xFF), String.format("%02X", crc[1] & 0xFF),
|
|
||||||
String.format("%02X", crcLo), String.format("%02X", crcHi));
|
|
||||||
}
|
|
||||||
return valid;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void fail(long frameLength) {
|
private void fail(long frameLength) {
|
||||||
|
|||||||
@ -114,4 +114,10 @@ public class ThingsModelValueItem {
|
|||||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date ts;
|
private Date ts;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建时间(用于排序)
|
||||||
|
*/
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date createTime;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -599,6 +599,7 @@ public class ThingsModelServiceImpl implements IThingsModelService {
|
|||||||
arrayObjectThingsModel.setIsReadonly(param.getIsReadonly());
|
arrayObjectThingsModel.setIsReadonly(param.getIsReadonly());
|
||||||
arrayObjectThingsModel.setDatatype(param.getDatatype());
|
arrayObjectThingsModel.setDatatype(param.getDatatype());
|
||||||
arrayObjectThingsModel.setModelOrder(thingsModel.getModelOrder());
|
arrayObjectThingsModel.setModelOrder(thingsModel.getModelOrder());
|
||||||
|
arrayObjectThingsModel.setCreateTime(thingsModel.getCreateTime());
|
||||||
resultList.add(arrayObjectThingsModel);
|
resultList.add(arrayObjectThingsModel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -617,6 +618,7 @@ public class ThingsModelServiceImpl implements IThingsModelService {
|
|||||||
arrayThingsModel.setIsReadonly(thingsModel.getIsReadonly());
|
arrayThingsModel.setIsReadonly(thingsModel.getIsReadonly());
|
||||||
arrayThingsModel.setDatatype(datatype);
|
arrayThingsModel.setDatatype(datatype);
|
||||||
arrayThingsModel.setModelOrder(thingsModel.getModelOrder());
|
arrayThingsModel.setModelOrder(thingsModel.getModelOrder());
|
||||||
|
arrayThingsModel.setCreateTime(thingsModel.getCreateTime());
|
||||||
resultList.add(arrayThingsModel);
|
resultList.add(arrayThingsModel);
|
||||||
}
|
}
|
||||||
} else if ("object".equals(datatype.getType())) {
|
} else if ("object".equals(datatype.getType())) {
|
||||||
@ -630,6 +632,7 @@ public class ThingsModelServiceImpl implements IThingsModelService {
|
|||||||
newObjectThingsModel.setIsReadonly(objectThingsModel.getIsReadonly());
|
newObjectThingsModel.setIsReadonly(objectThingsModel.getIsReadonly());
|
||||||
newObjectThingsModel.setDatatype(objectThingsModel.getDatatype());
|
newObjectThingsModel.setDatatype(objectThingsModel.getDatatype());
|
||||||
newObjectThingsModel.setModelOrder(thingsModel.getModelOrder());
|
newObjectThingsModel.setModelOrder(thingsModel.getModelOrder());
|
||||||
|
newObjectThingsModel.setCreateTime(thingsModel.getCreateTime());
|
||||||
resultList.add(newObjectThingsModel);
|
resultList.add(newObjectThingsModel);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -642,6 +645,7 @@ public class ThingsModelServiceImpl implements IThingsModelService {
|
|||||||
otherThingsModel.setIsReadonly(thingsModel.getIsReadonly());
|
otherThingsModel.setIsReadonly(thingsModel.getIsReadonly());
|
||||||
otherThingsModel.setDatatype(datatype);
|
otherThingsModel.setDatatype(datatype);
|
||||||
otherThingsModel.setModelOrder(thingsModel.getModelOrder());
|
otherThingsModel.setModelOrder(thingsModel.getModelOrder());
|
||||||
|
otherThingsModel.setCreateTime(thingsModel.getCreateTime());
|
||||||
resultList.add(otherThingsModel);
|
resultList.add(otherThingsModel);
|
||||||
}
|
}
|
||||||
return resultList;
|
return resultList;
|
||||||
@ -686,24 +690,31 @@ public class ThingsModelServiceImpl implements IThingsModelService {
|
|||||||
if (null == productId) {
|
if (null == productId) {
|
||||||
return new ArrayList<>();
|
return new ArrayList<>();
|
||||||
}
|
}
|
||||||
// 1、获取产品物模型
|
// 排序器:按 modelOrder 降序,createTime 降序(与数据库 SQL 一致)
|
||||||
|
Comparator<ThingsModelDTO> modelComparator = Comparator
|
||||||
|
.comparing(ThingsModelDTO::getModelOrder, Comparator.reverseOrder())
|
||||||
|
.thenComparing(ThingsModelDTO::getCreateTime, Comparator.nullsLast(Comparator.reverseOrder()));
|
||||||
|
|
||||||
|
// 1、获取产品物模型并排序
|
||||||
Map<String, ThingsModelValueItem> map = itslCache.getCacheThMapByProductId(productId);
|
Map<String, ThingsModelValueItem> map = itslCache.getCacheThMapByProductId(productId);
|
||||||
List<ThingsModelDTO> thingsModelDTOList = new ArrayList<>();
|
List<ThingsModelDTO> thingsModelDTOList = new ArrayList<>();
|
||||||
for (Map.Entry<String, ThingsModelValueItem> entry : map.entrySet()) {
|
for (Map.Entry<String, ThingsModelValueItem> entry : map.entrySet()) {
|
||||||
ThingsModel thingsModel = this.propertyDtoChangeThingsModel(entry.getValue());
|
ThingsModel thingsModel = this.propertyDtoChangeThingsModel(entry.getValue());
|
||||||
thingsModelDTOList.addAll(this.changeObjectOrArray(thingsModel));
|
thingsModelDTOList.addAll(this.changeObjectOrArray(thingsModel));
|
||||||
}
|
}
|
||||||
|
thingsModelDTOList.sort(modelComparator);
|
||||||
|
|
||||||
// 2. 获取设备级计算物模型并合并
|
// 2. 获取设备级计算物模型并合并
|
||||||
if (StringUtils.isNotEmpty(serialNumber)) {
|
if (StringUtils.isNotEmpty(serialNumber)) {
|
||||||
Map<String, ThingsModelValueItem> deviceCalculatedMap = itslCache.getDeviceCalculatedModelMap(serialNumber);
|
Map<String, ThingsModelValueItem> deviceCalculatedMap = itslCache.getDeviceCalculatedModelMap(serialNumber);
|
||||||
|
List<ThingsModelDTO> deviceModelList = new ArrayList<>();
|
||||||
for (Map.Entry<String, ThingsModelValueItem> entry : deviceCalculatedMap.entrySet()) {
|
for (Map.Entry<String, ThingsModelValueItem> entry : deviceCalculatedMap.entrySet()) {
|
||||||
ThingsModel thingsModel = this.propertyDtoChangeThingsModel(entry.getValue());
|
ThingsModel thingsModel = this.propertyDtoChangeThingsModel(entry.getValue());
|
||||||
thingsModelDTOList.addAll(this.changeObjectOrArray(thingsModel));
|
deviceModelList.addAll(this.changeObjectOrArray(thingsModel));
|
||||||
}
|
}
|
||||||
|
deviceModelList.sort(modelComparator);
|
||||||
|
thingsModelDTOList.addAll(deviceModelList);
|
||||||
}
|
}
|
||||||
|
|
||||||
thingsModelDTOList.sort(Comparator.comparing(ThingsModelDTO::getModelOrder));
|
|
||||||
if (StringUtils.isEmpty(serialNumber)) {
|
if (StringUtils.isEmpty(serialNumber)) {
|
||||||
return thingsModelDTOList;
|
return thingsModelDTOList;
|
||||||
}
|
}
|
||||||
@ -767,6 +778,7 @@ public class ThingsModelServiceImpl implements IThingsModelService {
|
|||||||
thingsModel.setSpecs(JSON.toJSONString(valueItem.getDatatype()));
|
thingsModel.setSpecs(JSON.toJSONString(valueItem.getDatatype()));
|
||||||
thingsModel.setType(valueItem.getType());
|
thingsModel.setType(valueItem.getType());
|
||||||
thingsModel.setModelId(valueItem.getModelId());
|
thingsModel.setModelId(valueItem.getModelId());
|
||||||
|
thingsModel.setCreateTime(valueItem.getCreateTime());
|
||||||
return thingsModel;
|
return thingsModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
14
vue/package-lock.json
generated
14
vue/package-lock.json
generated
@ -5751,6 +5751,15 @@
|
|||||||
"zrender": "5.6.1"
|
"zrender": "5.6.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"echarts-extension-leaflet": {
|
||||||
|
"version": "1.2.2",
|
||||||
|
"resolved": "https://registry.npmmirror.com/echarts-extension-leaflet/-/echarts-extension-leaflet-1.2.2.tgz",
|
||||||
|
"integrity": "sha512-EKZmIQDRqxnf6DtYWqujn2PRqHmEAq3yr0gsZAwmOT9rSy0Rwt9FlXKPjK3d+EVLqT6se6IQweyJTsqMg537Gg==",
|
||||||
|
"requires": {
|
||||||
|
"echarts": "^5.5.0",
|
||||||
|
"leaflet": "^1.9.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"echarts-liquidfill": {
|
"echarts-liquidfill": {
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
"resolved": "https://registry.npmmirror.com/echarts-liquidfill/-/echarts-liquidfill-3.1.0.tgz",
|
"resolved": "https://registry.npmmirror.com/echarts-liquidfill/-/echarts-liquidfill-3.1.0.tgz",
|
||||||
@ -8974,6 +8983,11 @@
|
|||||||
"launch-editor": "^2.12.0"
|
"launch-editor": "^2.12.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"leaflet": {
|
||||||
|
"version": "1.9.4",
|
||||||
|
"resolved": "https://registry.npmmirror.com/leaflet/-/leaflet-1.9.4.tgz",
|
||||||
|
"integrity": "sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA=="
|
||||||
|
},
|
||||||
"leven": {
|
"leven": {
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmmirror.com/leven/-/leven-2.1.0.tgz",
|
"resolved": "https://registry.npmmirror.com/leven/-/leven-2.1.0.tgz",
|
||||||
|
|||||||
@ -46,6 +46,7 @@
|
|||||||
"codemirror": "^5.65.2",
|
"codemirror": "^5.65.2",
|
||||||
"core-js": "3.25.3",
|
"core-js": "3.25.3",
|
||||||
"echarts": "^5.4.0",
|
"echarts": "^5.4.0",
|
||||||
|
"echarts-extension-leaflet": "^1.2.2",
|
||||||
"echarts-liquidfill": "^3.0.6",
|
"echarts-liquidfill": "^3.0.6",
|
||||||
"element-china-area-data": "^4.1.1",
|
"element-china-area-data": "^4.1.1",
|
||||||
"element-ui": "2.15.10",
|
"element-ui": "2.15.10",
|
||||||
|
|||||||
@ -1,28 +1,66 @@
|
|||||||
export function loadBMap() {
|
// 使用OpenStreetMap和Leaflet替代百度地图
|
||||||
return new Promise(function(resolve, reject) {
|
|
||||||
if (typeof BMap !== 'undefined') {
|
export function loadMap() {
|
||||||
resolve(BMap)
|
|
||||||
return true
|
return new Promise(function(resolve, reject) {
|
||||||
}
|
// eslint-disable-next-line no-undef
|
||||||
window.onBMapCallback = function() {
|
if (typeof L !== 'undefined') {
|
||||||
resolve(BMap)
|
// eslint-disable-next-line no-undef
|
||||||
}
|
resolve(L);
|
||||||
// 使用https协议需要添加一下meta标签
|
return true;
|
||||||
var protocolStr = document.location.protocol;
|
}
|
||||||
if(protocolStr == "https:")
|
|
||||||
{
|
// 加载Leaflet CSS
|
||||||
let meta = document.createElement('meta')
|
if (!document.querySelector('link[href*="leaflet.css"]')) {
|
||||||
meta.httpEquiv = 'Content-Security-Policy'
|
const link = document.createElement('link');
|
||||||
meta.content ='upgrade-insecure-requests'
|
link.rel = 'stylesheet';
|
||||||
meta.onerror = reject
|
link.href = 'https://unpkg.com/leaflet@1.9.4/dist/leaflet.css';
|
||||||
document.head.appendChild(meta)
|
link.integrity = 'sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY=';
|
||||||
}
|
link.crossOrigin = '';
|
||||||
// 引入百度地图
|
document.head.appendChild(link);
|
||||||
let script = document.createElement('script')
|
}
|
||||||
script.type = 'text/javascript'
|
|
||||||
script.src =
|
// 加载Leaflet JS
|
||||||
'http://api.map.baidu.com/api?v=2.0&ak='+ process.env.VUE_APP_BAI_DU_AK +'&s=1&__ec_v__=20190126&callback=onBMapCallback'
|
const script = document.createElement('script');
|
||||||
script.onerror = reject
|
script.type = 'text/javascript';
|
||||||
document.head.appendChild(script)
|
script.src = 'https://unpkg.com/leaflet@1.9.4/dist/leaflet.js';
|
||||||
})
|
script.integrity = 'sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo=';
|
||||||
|
script.crossOrigin = '';
|
||||||
|
script.onload = function() {
|
||||||
|
// eslint-disable-next-line no-undef
|
||||||
|
resolve(L);
|
||||||
|
};
|
||||||
|
script.onerror = reject;
|
||||||
|
document.head.appendChild(script);
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// export function loadBMap() {
|
||||||
|
// return new Promise(function(resolve, reject) {
|
||||||
|
// if (typeof BMap !== 'undefined') {
|
||||||
|
// resolve(BMap)
|
||||||
|
// return true
|
||||||
|
// }
|
||||||
|
// window.onBMapCallback = function() {
|
||||||
|
// resolve(BMap)
|
||||||
|
// }
|
||||||
|
// // 使用https协议需要添加一下meta标签
|
||||||
|
// var protocolStr = document.location.protocol;
|
||||||
|
// if(protocolStr == "https:")
|
||||||
|
// {
|
||||||
|
// let meta = document.createElement('meta')
|
||||||
|
// meta.httpEquiv = 'Content-Security-Policy'
|
||||||
|
// meta.content ='upgrade-insecure-requests'
|
||||||
|
// meta.onerror = reject
|
||||||
|
// document.head.appendChild(meta)
|
||||||
|
// }
|
||||||
|
// // 引入百度地图
|
||||||
|
// let script = document.createElement('script')
|
||||||
|
// script.type = 'text/javascript'
|
||||||
|
// script.src =
|
||||||
|
// 'http://api.map.baidu.com/api?v=2.0&ak='+ process.env.VUE_APP_BAI_DU_AK +'&s=1&__ec_v__=20190126&callback=onBMapCallback'
|
||||||
|
// script.onerror = reject
|
||||||
|
// document.head.appendChild(script)
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
|||||||
@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import {
|
import {
|
||||||
loadBMap
|
loadMap
|
||||||
} from '@/utils/map.js'
|
} from '@/utils/map.js'
|
||||||
//安装的是echarts完整包,里面包含百度地图扩展,路径为 echarts/extension/bmap/bmap.js,将其引入
|
//安装的是echarts完整包,里面包含百度地图扩展,路径为 echarts/extension/bmap/bmap.js,将其引入
|
||||||
//ECharts的百度地图扩展,可以在百度地图上展现点图,线图,热力图等可视化
|
//ECharts的百度地图扩展,可以在百度地图上展现点图,线图,热力图等可视化
|
||||||
@ -65,7 +65,7 @@ export default {
|
|||||||
},
|
},
|
||||||
/**加载地图*/
|
/**加载地图*/
|
||||||
loadMap() {
|
loadMap() {
|
||||||
loadBMap().then(() => {
|
loadMap().then(() => {
|
||||||
this.getmap();
|
this.getmap();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -31,19 +31,25 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="item-content">
|
<div class="item-content">
|
||||||
<div class="content-value">
|
<div class="content-value">
|
||||||
<!-- 根据format选择显示HEX或ASCII格式 -->
|
<!-- 自动识别并展示所有可用格式 -->
|
||||||
<div v-if="format === 'Hex' && item.value" class="data-format-item">
|
<!-- JSON格式优先展示(如果是有效JSON) -->
|
||||||
<span class="format-label">HEX:</span>
|
<div v-if="isValidJson(item.valueAscii || item.value)" class="data-format-item json-item">
|
||||||
<span class="hex-value">{{ item.value }}</span>
|
|
||||||
</div>
|
|
||||||
<div v-if="format === 'ASCII' && item.valueAscii" class="data-format-item ascii-item">
|
|
||||||
<span class="format-label">ASCII:</span>
|
|
||||||
<pre class="ascii-value">{{ item.valueAscii }}</pre>
|
|
||||||
</div>
|
|
||||||
<div v-if="format === 'JSON'" class="data-format-item">
|
|
||||||
<span class="format-label">JSON:</span>
|
<span class="format-label">JSON:</span>
|
||||||
<pre class="json-value">{{ formatJsonValue(item.value, item.valueAscii) }}</pre>
|
<pre class="json-value">{{ formatJsonValue(item.value, item.valueAscii) }}</pre>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- 非JSON时展示HEX和ASCII -->
|
||||||
|
<template v-else>
|
||||||
|
<!-- HEX格式 -->
|
||||||
|
<div v-if="item.value" class="data-format-item">
|
||||||
|
<span class="format-label">HEX:</span>
|
||||||
|
<span class="hex-value">{{ item.value }}</span>
|
||||||
|
</div>
|
||||||
|
<!-- ASCII格式(如果有可读内容) -->
|
||||||
|
<div v-if="item.valueAscii && hasReadableAscii(item.valueAscii)" class="data-format-item ascii-item">
|
||||||
|
<span class="format-label">ASCII:</span>
|
||||||
|
<pre class="ascii-value">{{ item.valueAscii }}</pre>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="analysis-data" v-if="item.type != 0 && item.analysis">
|
<div class="analysis-data" v-if="item.type != 0 && item.analysis">
|
||||||
@ -564,6 +570,24 @@ export default {
|
|||||||
}
|
}
|
||||||
// 如果都不是JSON,返回提示信息
|
// 如果都不是JSON,返回提示信息
|
||||||
return '数据不是有效的JSON格式';
|
return '数据不是有效的JSON格式';
|
||||||
|
},
|
||||||
|
/**判断是否为有效的JSON */
|
||||||
|
isValidJson(value) {
|
||||||
|
if (!value) return false;
|
||||||
|
try {
|
||||||
|
const parsed = JSON.parse(value);
|
||||||
|
// 确保是对象或数组,而不是简单值
|
||||||
|
return typeof parsed === 'object' && parsed !== null;
|
||||||
|
} catch (e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/**判断ASCII是否包含可读内容 */
|
||||||
|
hasReadableAscii(asciiValue) {
|
||||||
|
if (!asciiValue) return false;
|
||||||
|
// 检查是否有可打印字符(排除纯控制字符)
|
||||||
|
const printableRegex = /[\x20-\x7E]/;
|
||||||
|
return printableRegex.test(asciiValue) && asciiValue.trim().length > 0;
|
||||||
},
|
},
|
||||||
/**打开编辑框 */
|
/**打开编辑框 */
|
||||||
openEdit() {
|
openEdit() {
|
||||||
@ -990,6 +1014,11 @@ $right-btn-color: #1890ff;
|
|||||||
}
|
}
|
||||||
|
|
||||||
.right {
|
.right {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
// 高度 = 头部36px + 内容700px + 底部64px
|
||||||
|
height: 800px;
|
||||||
|
|
||||||
.right-head {
|
.right-head {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
@ -997,19 +1026,28 @@ $right-btn-color: #1890ff;
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 覆盖通用 .content 样式
|
||||||
|
.content.beautify-scroll-def {
|
||||||
|
flex: 1;
|
||||||
|
height: auto;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: flex-end;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.quick-item {
|
.quick-item {
|
||||||
width: 80%;
|
width: 80%;
|
||||||
margin: auto;
|
margin: 0 auto 12px auto;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
line-height: 36px;
|
line-height: 36px;
|
||||||
margin-top: 12px;
|
|
||||||
border: 1px solid $right-btn-color;
|
border: 1px solid $right-btn-color;
|
||||||
color: $right-btn-color;
|
color: $right-btn-color;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
|
|
||||||
&:last-child {
|
&:first-child {
|
||||||
margin-bottom: 12px;
|
margin-top: 12px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user