Files
Web_CRICS_Server_VS2010_Prod/WebSite/touchuantest.htm

1076 lines
36 KiB
HTML
Raw Normal View History

2025-12-11 09:17:16 +08:00
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>透传设置界面</title>
<style type="text/css">
*
{
box-sizing: border-box;
margin: 0;
padding: 0;
}
2026-01-09 13:45:30 +08:00
:root
{
--primary-color: #4361ee;
--primary-hover: #3a56d4;
--success-color: #2ecc71;
--success-hover: #27ae60;
--warning-color: #f39c12;
--danger-color: #e74c3c;
--light-bg: #f8f9fa;
--card-bg: #ffffff;
--border-color: #e9ecef;
--text-primary: #2c3e50;
--text-secondary: #7f8c8d;
--shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
--radius: 10px;
--transition: all 0.3s ease;
}
2025-12-11 09:17:16 +08:00
body
{
2026-01-09 13:45:30 +08:00
font-family: 'Segoe UI' , 'PingFang SC' , 'Microsoft YaHei' , sans-serif;
line-height: 1.6;
color: var(--text-primary);
background: linear-gradient(135deg, #f5f7fa 0%, #e4e8f0 100%);
2026-01-09 14:52:58 +08:00
padding: 12px;
2026-01-09 13:45:30 +08:00
min-height: 100vh;
}
.container
{
2026-01-09 14:52:58 +08:00
max-width: 1440px;
2025-12-11 09:17:16 +08:00
margin: 0 auto;
}
.card
{
2026-01-09 13:45:30 +08:00
background: var(--card-bg);
border-radius: var(--radius);
box-shadow: var(--shadow);
2026-01-09 14:52:58 +08:00
margin-bottom: 10px;
2026-01-09 13:45:30 +08:00
border: 1px solid var(--border-color);
transition: var(--transition);
2025-12-11 09:17:16 +08:00
overflow: hidden;
}
2026-01-09 13:45:30 +08:00
.card:hover
{
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.12);
}
2025-12-11 09:17:16 +08:00
.card-header
{
2026-01-09 15:01:25 +08:00
background: linear-gradient(135deg, #24b6aa, #1ba59e);
2026-01-09 13:45:30 +08:00
color: white;
2026-01-09 14:52:58 +08:00
padding: 8px 12px;
2025-12-11 09:17:16 +08:00
font-weight: 600;
2026-01-09 14:52:58 +08:00
font-size: 1rem;
2026-01-09 13:45:30 +08:00
display: flex;
align-items: center;
}
.card-header i
{
margin-right: 10px;
font-size: 1.2rem;
2025-12-11 09:17:16 +08:00
}
.card-content
{
2026-01-09 14:52:58 +08:00
padding: 10px 12px;
2025-12-11 09:17:16 +08:00
}
.form-row
{
display: flex;
2026-01-09 14:52:58 +08:00
align-items: center;
flex-wrap: nowrap;
gap: 8px;
margin-bottom: 8px;
overflow-x: auto;
2025-12-11 09:17:16 +08:00
}
2026-01-09 14:52:58 +08:00
/* 使主机编号行内排列 */
.form-row > .form-group:first-child {
flex-direction: row;
align-items: center;
gap: 8px;
min-width: 0;
}
/* 状态放最右 */
.form-row .status-indicator {
margin-left: auto;
align-self: center;
}
/* 单行显示单选项 */
.radio-options { flex-wrap: nowrap; gap: 8px; }
.checkbox-group label, .radio-option label { font-size: 0.85rem; margin-bottom: 0; }
2025-12-11 09:17:16 +08:00
.form-group
{
display: flex;
flex-direction: column;
2026-01-09 14:52:58 +08:00
flex: 0 1 auto;
min-width: 0;
2025-12-11 09:17:16 +08:00
}
.form-row-inline
{
display: flex;
align-items: center;
2026-01-09 14:52:58 +08:00
flex-wrap: nowrap;
gap: 8px;
margin-bottom: 8px;
padding: 6px 8px;
2026-01-09 13:45:30 +08:00
background-color: #f8fafc;
2026-01-09 14:52:58 +08:00
border-radius: 6px;
overflow-x: auto;
2025-12-11 09:17:16 +08:00
}
label
{
2026-01-09 14:52:58 +08:00
font-size: 0.85rem;
2025-12-11 09:17:16 +08:00
font-weight: 600;
2026-01-09 14:52:58 +08:00
margin-bottom: 6px;
2026-01-09 13:45:30 +08:00
color: var(--text-primary);
display: flex;
align-items: center;
}
.label-icon
{
margin-right: 6px;
color: var(--primary-color);
2025-12-11 09:17:16 +08:00
}
2026-01-09 13:45:30 +08:00
input, textarea, select, button
2025-12-11 09:17:16 +08:00
{
font-family: inherit;
2026-01-09 13:45:30 +08:00
font-size: 0.95rem;
transition: var(--transition);
2025-12-11 09:17:16 +08:00
}
2026-01-09 13:45:30 +08:00
input[type="text"], input[type="number"], textarea, select
2025-12-11 09:17:16 +08:00
{
2026-01-09 14:52:58 +08:00
padding: 6px 8px;
2026-01-09 13:45:30 +08:00
border: 2px solid #e0e6ef;
2026-01-09 14:52:58 +08:00
border-radius: 6px;
2026-01-09 13:45:30 +08:00
background-color: #fff;
transition: var(--transition);
2026-01-09 14:52:58 +08:00
height: 32px;
2025-12-11 09:17:16 +08:00
}
2026-01-09 13:45:30 +08:00
input[type="text"]:focus, input[type="number"]:focus, textarea:focus, select:focus
2025-12-11 09:17:16 +08:00
{
outline: none;
2026-01-09 13:45:30 +08:00
border-color: var(--primary-color);
box-shadow: 0 0 0 3px rgba(67, 97, 238, 0.15);
2025-12-11 09:17:16 +08:00
}
textarea
{
2026-01-09 14:52:58 +08:00
min-height: 64px;
2025-12-11 09:17:16 +08:00
resize: vertical;
width: 100%;
2026-01-09 14:52:58 +08:00
line-height: 1.4;
2025-12-11 09:17:16 +08:00
}
button
{
2026-01-09 13:45:30 +08:00
background-color: var(--primary-color);
2025-12-11 09:17:16 +08:00
color: white;
border: none;
2026-01-09 13:45:30 +08:00
border-radius: 8px;
2026-01-09 14:52:58 +08:00
padding: 10px 16px;
2025-12-11 09:17:16 +08:00
cursor: pointer;
2026-01-09 13:45:30 +08:00
font-weight: 600;
display: inline-flex;
align-items: center;
justify-content: center;
transition: var(--transition);
2025-12-11 09:17:16 +08:00
}
button:hover
{
2026-01-09 13:45:30 +08:00
background-color: var(--primary-hover);
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(67, 97, 238, 0.25);
}
button:active
{
transform: translateY(0);
2025-12-11 09:17:16 +08:00
}
#send
{
2026-01-09 13:45:30 +08:00
background-color: var(--success-color);
2025-12-11 09:17:16 +08:00
}
#send:hover
{
2026-01-09 13:45:30 +08:00
background-color: var(--success-hover);
}
.checkbox-group, .radio-group
{
display: flex;
align-items: center;
gap: 8px;
}
.radio-options
{
display: flex;
flex-wrap: wrap;
2026-01-09 14:52:58 +08:00
gap: 10px;
margin-bottom: 12px;
2026-01-09 13:45:30 +08:00
}
.radio-option
{
display: flex;
align-items: center;
2026-01-09 14:52:58 +08:00
gap: 6px;
padding: 6px 8px;
2026-01-09 13:45:30 +08:00
background-color: #f8fafc;
2026-01-09 14:52:58 +08:00
border-radius: 6px;
2026-01-09 13:45:30 +08:00
border: 2px solid #e0e6ef;
cursor: pointer;
transition: var(--transition);
2026-01-09 14:52:58 +08:00
font-size: 0.92rem;
2026-01-09 13:45:30 +08:00
}
.radio-option:hover
{
border-color: var(--primary-color);
background-color: #f0f4ff;
}
.radio-option input[type="radio"]
{
margin-right: 5px;
}
.port-group
{
display: grid;
2026-01-09 14:52:58 +08:00
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
gap: 8px;
margin-bottom: 8px;
2026-01-09 13:45:30 +08:00
}
.port-item
{
display: flex;
flex-direction: column;
2026-01-09 14:52:58 +08:00
gap: 6px;
padding: 8px 10px;
2026-01-09 13:45:30 +08:00
background-color: #f8fafc;
2026-01-09 14:52:58 +08:00
border-radius: 6px;
2026-01-09 13:45:30 +08:00
display: none; /* 默认隐藏 */
}
.port-item.visible
{
display: flex; /* 显示时使用 flex 布局 */
}
.port-item-header
{
display: flex;
align-items: center;
justify-content: space-between;
}
.port-item-content
{
display: flex;
flex-wrap: wrap;
gap: 15px;
align-items: center;
}
.inline-group
{
display: flex;
align-items: center;
gap: 10px;
2025-12-11 09:17:16 +08:00
}
2026-01-09 13:45:30 +08:00
.input-with-label
2025-12-11 09:17:16 +08:00
{
display: flex;
align-items: center;
2026-01-09 14:52:58 +08:00
gap: 6px;
2025-12-11 09:17:16 +08:00
}
2026-01-09 13:45:30 +08:00
.input-with-label label
{
margin-bottom: 0;
white-space: nowrap;
}
2025-12-11 09:17:16 +08:00
.message-container
{
2026-01-09 14:52:58 +08:00
max-height: 95vh;
2025-12-11 09:17:16 +08:00
overflow-y: auto;
2026-01-09 13:45:30 +08:00
border: 1px solid var(--border-color);
border-radius: 8px;
2026-01-09 14:52:58 +08:00
padding: 8px;
2025-12-11 09:17:16 +08:00
background-color: #f8f9fa;
font-family: 'Courier New' , monospace;
2026-01-09 13:45:30 +08:00
font-size: 0.9rem;
2025-12-11 09:17:16 +08:00
}
2026-01-09 14:52:58 +08:00
.message-table
{
width: 100%;
border-collapse: collapse;
background: transparent;
}
.message-table th,
.message-table td
{
border-bottom: 1px solid #e9ecef;
padding: 6px 8px;
vertical-align: top;
word-break: break-all;
}
.message-table th
{
position: sticky;
top: 0;
background: #f8f9fa;
z-index: 1;
text-align: left;
font-weight: 700;
color: var(--text-primary);
}
.message-row-sent
{
background-color: #e8f5e9;
}
.message-row-received
{
background-color: #e3f2fd;
}
/* 紧凑布局样式 */
#btn_set { padding: 6px 10px; font-size: 0.92rem; height: 32px; }
#send { padding: 8px 12px; height: 34px; }
#txthostnumber { max-width: 300px; width: 300px; }
#protocoltype { width: 72px; }
#Port_2, #Byte_Speed, #moshi_id { width: 100px; }
#tm2, #tm4 { width: 100px; }
.form-row { gap: 8px; }
.form-row-inline { gap: 8px; }
/* 指定 port-group 内的 select 字体大小为 14px */
.port-group select, .port-item select { font-size: 12px; }
.port-group select option { font-size: 15px; }
2025-12-11 09:17:16 +08:00
.message-item
{
2026-01-09 13:45:30 +08:00
padding: 10px 12px;
2025-12-11 09:17:16 +08:00
border-bottom: 1px solid #e9ecef;
2026-01-09 13:45:30 +08:00
display: flex;
align-items: center;
2025-12-11 09:17:16 +08:00
}
.message-item:last-child
{
border-bottom: none;
}
2026-01-09 13:45:30 +08:00
.message-time
{
font-size: 0.8rem;
color: var(--text-secondary);
margin-right: 15px;
min-width: 120px;
display: flex;
flex-direction: column;
line-height: 1.2;
}
.message-delta
{
font-size: 0.75rem;
color: var(--text-secondary);
margin-top: 2px;
}
.message-content
{
flex: 1;
word-break: break-all;
}
.message-sent
{
background-color: #e8f5e9;
border-left: 4px solid var(--success-color);
}
.message-received
{
background-color: #e3f2fd;
border-left: 4px solid var(--primary-color);
}
2025-12-11 09:17:16 +08:00
#result
{
2026-01-09 13:45:30 +08:00
margin-top: 15px;
padding: 12px 15px;
border-radius: 8px;
font-size: 0.9rem;
display: none;
}
.success
{
background-color: #d4edda;
color: #155724;
border-left: 4px solid var(--success-color);
display: block !important;
}
.error
{
background-color: #f8d7da;
color: #721c24;
border-left: 4px solid var(--danger-color);
display: block !important;
}
.info-box
{
background-color: #e7f3ff;
border-left: 4px solid var(--primary-color);
2026-01-09 14:52:58 +08:00
padding: 8px 10px;
2026-01-09 13:45:30 +08:00
border-radius: 8px;
2026-01-09 14:52:58 +08:00
margin-bottom: 8px;
font-size: 0.88rem;
2026-01-09 13:45:30 +08:00
}
.status-indicator
{
display: inline-flex;
align-items: center;
2026-01-09 14:52:58 +08:00
gap: 6px;
padding: 4px 8px;
border-radius: 16px;
font-size: 0.82rem;
2026-01-09 13:45:30 +08:00
font-weight: 600;
}
.status-connected
{
background-color: #d4edda;
color: #155724;
}
.status-disconnected
{
background-color: #f8d7da;
color: #721c24;
}
.status-dot
{
width: 8px;
height: 8px;
border-radius: 50%;
}
.status-connected .status-dot
{
background-color: var(--success-color);
}
.status-disconnected .status-dot
{
background-color: var(--danger-color);
2025-12-11 09:17:16 +08:00
}
@media (max-width: 768px)
{
2026-01-09 13:45:30 +08:00
.container
{
padding: 10px;
}
.card-content
{
padding: 15px;
}
.form-row, .port-group
2025-12-11 09:17:16 +08:00
{
flex-direction: column;
2026-01-09 13:45:30 +08:00
gap: 15px;
2025-12-11 09:17:16 +08:00
}
.form-group
{
width: 100%;
2026-01-09 13:45:30 +08:00
min-width: auto;
}
.radio-options
{
flex-direction: column;
gap: 10px;
}
.port-item-content
{
flex-direction: column;
align-items: flex-start;
2025-12-11 09:17:16 +08:00
}
}
2026-01-09 13:45:30 +08:00
/* 自定义复选框和单选框样式 */
input[type="checkbox"], input[type="radio"]
{
width: 18px;
height: 18px;
cursor: pointer;
}
/* 滚动条样式 */
::-webkit-scrollbar
{
width: 8px;
}
::-webkit-scrollbar-track
{
background: #f1f1f1;
border-radius: 4px;
}
::-webkit-scrollbar-thumb
{
background: #c1c1c1;
border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover
{
background: #a8a8a8;
}
2025-12-11 09:17:16 +08:00
</style>
</head>
<body>
2026-01-09 13:45:30 +08:00
<div class="container">
2026-01-09 14:52:58 +08:00
<!-- 设置发送透传卡片(合并:设置透传 + 发送内容) -->
2026-01-09 13:45:30 +08:00
<div class="card">
<div class="card-header">
2026-01-09 14:52:58 +08:00
<i class="fas fa-cogs"></i>设置发送透传
2026-01-09 13:45:30 +08:00
</div>
<div class="card-content">
<div class="info-box">
<i class="fas fa-info-circle"></i>请输入主机编号以建立透传连接。连接成功后,您可以发送和接收数据。
2025-12-11 09:17:16 +08:00
</div>
2026-01-09 13:45:30 +08:00
<div class="form-row">
<div class="form-group">
<label for="txthostnumber">
<i class="fas fa-desktop label-icon"></i>主机编号:
</label>
<input id="txthostnumber" type="text" placeholder="请输入主机编号" required>
</div>
2026-01-09 14:52:58 +08:00
<div class="form-group" style="align-self: center;">
2026-01-09 13:45:30 +08:00
<button id="btn_set">
<i class="fas fa-plug"></i>连接设备
</button>
</div>
2026-01-09 14:52:58 +08:00
<div class="status-indicator status-disconnected" id="connection-status" style="margin-left:auto;">
<span class="status-dot"></span><span></span>
</div>
2026-01-09 13:45:30 +08:00
</div>
2026-01-09 14:52:58 +08:00
<div id="result"></div>
<div style="height: 12px;"></div>
2026-01-09 13:45:30 +08:00
<div class="form-row-inline">
<div class="checkbox-group">
<input id="isprotocol" type="checkbox" checked>
2026-01-09 14:52:58 +08:00
<label for="isprotocol" style="margin-bottom: 0;">自动加上协议头</label>
2026-01-09 13:45:30 +08:00
</div>
2026-01-09 14:52:58 +08:00
<div class="form-group" style="flex-direction: row; align-items: center; gap: 8px; flex: 0 1 auto;">
<label for="protocoltype" style="margin-bottom: 0;">协议类型:</label>
<input id="protocoltype" type="text" value="70" placeholder="默认是70" style="width: 72px;">
2026-01-09 13:45:30 +08:00
</div>
2026-01-09 14:52:58 +08:00
<div class="radio-options" style="flex-wrap:nowrap; margin-left:8px;">
<div class="radio-option">
<input id="readmode" type="radio" name="mode" value="读取模式" checked>
<label for="readmode" style="margin-bottom: 0;">读取模式</label>
</div>
<div class="radio-option">
<input id="setmode" type="radio" name="mode" value="设置模式">
<label for="setmode" style="margin-bottom: 0;">设置模式</label>
</div>
<div class="radio-option">
<input id="sendmode" type="radio" name="mode" value="发送模式">
<label for="sendmode" style="margin-bottom: 0;">发送模式</label>
</div>
2026-01-09 13:45:30 +08:00
</div>
2026-01-09 14:52:58 +08:00
</div>
2026-01-09 13:45:30 +08:00
<div class="port-group">
<div class="port-item visible" id="p1">
<div class="port-item-header">
<span><strong>Port 1</strong></span>
</div>
<div class="port-item-content">
<div class="input-with-label">
2026-01-09 14:52:58 +08:00
<label>端口:</label>
2026-01-09 13:45:30 +08:00
<select id="Port_1">
<option value="01">轮询</option>
<option value="02">主动</option>
<option value="03">总线BUS</option>
</select>
</div>
</div>
</div>
<div class="port-item" id="p2">
<div class="port-item-header">
<span><strong>Port 2</strong></span>
</div>
<div class="port-item-content">
<div class="input-with-label">
2026-01-09 14:52:58 +08:00
<label>模式:</label>
<select id="Port_2" style="width: 100px;">
2026-01-09 13:45:30 +08:00
<option value="01">轮询</option>
<option value="02">主动</option>
<option value="03">总线BUS</option>
</select>
</div>
<div class="input-with-label">
2026-01-09 14:52:58 +08:00
<label>超时:</label>
<input type="text" name="timeout" id="tm2" placeholder="超时16进制" style="width: 100px;" />
2026-01-09 13:45:30 +08:00
</div>
<div class="port-item-content">
<div class="input-with-label">
2026-01-09 14:52:58 +08:00
<label>波特率:</label>
<select id="Byte_Speed" style="width: 100px;">
2026-01-09 13:45:30 +08:00
<option value="01">9600</option>
<option value="02">14400</option>
<option value="03">19200</option>
<option value="04">38400</option>
<option value="05">56000</option>
</select>
</div>
<div class="input-with-label">
2026-01-09 14:52:58 +08:00
<label>模式:</label>
<select id="moshi_id" style="width: 100px;">
2026-01-09 13:45:30 +08:00
<option value="01">正常模式</option>
<option value="02">进入透传</option>
<option value="03">进入监控</option>
</select>
</div>
</div>
</div>
</div>
<div class="port-item" id="p3">
<div class="port-item-header">
<span><strong>Port 4</strong></span>
</div>
<div class="port-item-content">
<div class="input-with-label">
2026-01-09 14:52:58 +08:00
<label>端口:</label>
2026-01-09 13:45:30 +08:00
<select id="Port_4">
<option value="01">轮询</option>
<option value="02">主动</option>
<option value="03">总线BUS</option>
</select>
</div>
<div class="input-with-label">
2026-01-09 14:52:58 +08:00
<label>超时:</label>
<input type="text" name="timeout" id="tm4" placeholder="超时(16进制)" style="width: 100px;" />
2026-01-09 13:45:30 +08:00
</div>
</div>
</div>
</div>
2026-01-09 14:52:58 +08:00
2026-01-09 13:45:30 +08:00
<div id="div_content">
<div class="form-group">
<label for="content">
<i class="fas fa-code label-icon"></i>透传内容16进制:
</label>
<textarea id="content" placeholder="请输入16进制内容例如: 01 02 03 0A 0B"></textarea>
</div>
</div>
2026-01-09 14:52:58 +08:00
<div style="display: flex; justify-content: flex-start; margin-top: 8px;">
2026-01-09 13:45:30 +08:00
<button id="send">
<i class="fas fa-paper-plane"></i>发送内容
</button>
2025-12-11 09:17:16 +08:00
</div>
</div>
</div>
2026-01-09 13:45:30 +08:00
<!-- 接收数据卡片 -->
<div class="card">
<div class="card-header">
2026-01-09 14:52:58 +08:00
<i class="fas fa-download"></i>下位机透传数据
2026-01-09 13:45:30 +08:00
</div>
<div class="card-content">
<div id="touchuan_content" class="message-container">
2026-01-09 14:52:58 +08:00
<table class="message-table">
<thead>
<tr>
<th style="width: 130px;">时间</th>
<th style="width: 70px;">间隔</th>
<th style="width: 90px;">设备</th>
<th style="width: 80px;">地址</th>
<th style="width: 90px;">设备类型</th>
<th style="width: 120px;">参数</th>
<th>原始数据</th>
</tr>
</thead>
<tbody id="touchuan_tbody">
</tbody>
</table>
2026-01-09 13:45:30 +08:00
</div>
<div style="display: flex; justify-content: space-between; margin-top: 15px;">
<button id="clear-btn" style="background-color: var(--text-secondary);">
<i class="fas fa-trash"></i>清空记录
</button>
</div>
2025-12-11 09:17:16 +08:00
</div>
</div>
</div>
<script src="Scripts/jquery-1.8.3.min.js" type="text/javascript"></script>
<script src="Scripts/mqtt.min.js" type="text/javascript"></script>
2026-01-09 13:45:30 +08:00
<script type="text/javascript">
// 连接状态
let isConnected = false;
let isPaused = false;
let mqttClient = null;
// 上一条“接收(设备上报)”消息到达时间(用于计算时间差,毫秒)
let lastReceivedAtMs = null;
// 获取当前时间
function getCurrentTime(date) {
const now = date || new Date();
return `${now.getHours().toString().padStart(2, '0')}:` +
`${now.getMinutes().toString().padStart(2, '0')}:` +
`${now.getSeconds().toString().padStart(2, '0')}.` +
`${now.getMilliseconds().toString().padStart(3, '0')}`;
}
// MQTT 接收数据裁剪:去掉前 17 字节固定头、去掉末尾 2 字节 CRC仅保留中间 payload
// 例AA 55 ... 02 01 [payload...] 20 A9
function extractMiddlePayload(hexString) {
if (!hexString) return '';
// 提取 2位十六进制 token忽略空格/其它分隔符
const tokens = (hexString.match(/[0-9a-fA-F]{2}/g) || []).map(t => t.toUpperCase());
if (tokens.length === 0) return '';
const headerLen = 17;
const crcLen = 2;
if (tokens.length <= headerLen + crcLen) {
return tokens.join(' ');
}
return tokens.slice(headerLen, tokens.length - crcLen).join(' ');
}
// 添加消息到显示区域
function addMessage(content,is_sent) {
if (isPaused) return;
const nowMs = Date.now();
const nowDate = new Date(nowMs);
2026-01-09 14:52:58 +08:00
let messageRowClass = 'message-row-received';
2026-01-09 13:45:30 +08:00
if (is_sent)
{
2026-01-09 14:52:58 +08:00
messageRowClass="message-row-sent";
2026-01-09 13:45:30 +08:00
}
// 仅对“接收”消息计算与上一条接收消息的时间差(毫秒)
2026-01-09 14:52:58 +08:00
let deltaText = '-';
2026-01-09 13:45:30 +08:00
if (!is_sent) {
content = extractMiddlePayload(content);
if (lastReceivedAtMs !== null) {
const deltaMs = nowMs - lastReceivedAtMs;
2026-01-09 14:52:58 +08:00
// 间隔列:仅显示毫秒数字,不带单位
deltaText = `${deltaMs}`;
2026-01-09 13:45:30 +08:00
}
lastReceivedAtMs = nowMs;
}
2026-01-09 14:52:58 +08:00
let messageRow = `
<tr class="${messageRowClass}">
<td>${getCurrentTime(nowDate)}</td>
<td>${deltaText}</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td>${content}</td>
</tr>
2026-01-09 13:45:30 +08:00
`;
2026-01-09 14:52:58 +08:00
$("#touchuan_tbody").append(messageRow);
2026-01-09 13:45:30 +08:00
// 自动滚动到底部
$("#touchuan_content").scrollTop($("#touchuan_content")[0].scrollHeight);
}
// 连接MQTT
2025-12-11 09:17:16 +08:00
function lianjie(hghg) {
const options = {
clientId: 'touchuan_' + Math.random().toString(16).substr(2, 8),
username: "blwws",
password: "E!9~3~H=M.&2STW",
protocolVersion: 5
};
2026-01-09 13:45:30 +08:00
mqttClient = mqtt.connect("wss://gua.blv-oa.com:8084/mqtt", options);
mqttClient.on("connect", (error) => {
console.log("连接成功");
lastReceivedAtMs = null;
$("#result").html('<i class="fas fa-check-circle"></i> 连接成功').removeClass("error").addClass("success");
$("#connection-status")
.removeClass("status-disconnected")
.addClass("status-connected")
.html('<span class="status-dot"></span><span>已连接: ' + hghg + '</span>');
isConnected = true;
mqttClient.unsubscribe("blw/touchuan/report" + hghg);
mqttClient.subscribe("blw/touchuan/report/" + hghg, (err) => {
if (err) {
console.error("订阅失败:", err);
}
});
2025-12-11 09:17:16 +08:00
});
2026-01-09 13:45:30 +08:00
mqttClient.on("message", (topic, message) => {
2025-12-11 09:17:16 +08:00
var data = message.toString();
console.log(data);
2026-01-09 13:45:30 +08:00
addMessage(data, false);
});
mqttClient.on("error", (error) => {
console.error("连接错误:", error);
lastReceivedAtMs = null;
$("#result").html('<i class="fas fa-exclamation-triangle"></i> 连接错误: ' + error).removeClass("success").addClass("error");
$("#connection-status")
.removeClass("status-connected")
.addClass("status-disconnected")
.html('<span class="status-dot"></span><span>连接失败</span>');
isConnected = false;
2025-12-11 09:17:16 +08:00
});
}
2026-01-09 13:45:30 +08:00
// 显示/隐藏端口设置区域
function togglePortVisibility(selectedMode) {
// 隐藏所有端口设置区域
$(".port-item").removeClass("visible");
//$("#div_content").removeClass("visible");
$("#div_content").hide();
// 根据选择的模式显示对应的区域
if (selectedMode === "读取模式") {
$("#p1").addClass("visible");
} else if (selectedMode === "设置模式") {
$("#p2").addClass("visible");
} else if (selectedMode === "发送模式") {
$("#p3").addClass("visible");
$("#div_content").show();;
}
console.log("切换到模式:", selectedMode);
}
// 页面加载完成后执行
2025-12-11 09:17:16 +08:00
$(function() {
2026-01-09 13:45:30 +08:00
// 初始化:根据默认选中的模式显示对应区域
const initialMode = $("input[name='mode']:checked").val();
togglePortVisibility(initialMode);
// 设置连接按钮点击事件
2025-12-11 09:17:16 +08:00
$("#btn_set").click(function() {
2026-01-09 13:45:30 +08:00
let hhh = $("#txthostnumber").val().trim();
if (!hhh) {
$("#result").html('<i class="fas fa-exclamation-circle"></i> 请输入主机编号').removeClass("success").addClass("error");
$("#txthostnumber").focus();
return;
}
$("#result").html('<i class="fas fa-spinner fa-spin"></i> 正在连接...').removeClass("error success").show();
2026-01-09 14:52:58 +08:00
// 初始化记录:以“点击连接设备”的时间作为首条记录(不影响接收间隔计算)
$("#touchuan_tbody").append(`
<tr class="message-row-received">
<td>${getCurrentTime(new Date())}</td>
<td>-</td>
<td></td>
<td></td>
<td></td>
<td>连接设备</td>
<td>${hhh}</td>
</tr>
`);
$("#touchuan_content").scrollTop($("#touchuan_content")[0].scrollHeight);
2026-01-09 13:45:30 +08:00
2025-12-11 09:17:16 +08:00
let mac = "";
let jjj = {
hostnumber: hhh,
mac: mac,
add_or_remove: "add"
};
2026-01-09 13:45:30 +08:00
2025-12-11 09:17:16 +08:00
$.ajax({
url: '/api/SetTouChuanData',
2026-01-09 13:45:30 +08:00
type: 'POST',
2025-12-11 09:17:16 +08:00
contentType: 'application/x-www-form-urlencoded',
data: jjj,
success: function(response) {
console.log(response);
2026-01-09 13:45:30 +08:00
$("#result").html('<i class="fas fa-check-circle"></i> 设置成功: ' + response).removeClass("error").addClass("success");
2025-12-11 09:17:16 +08:00
lianjie(hhh);
},
error: function(xhr, status, error) {
console.log(error);
2026-01-09 13:45:30 +08:00
$("#result").html('<i class="fas fa-times-circle"></i> 设置失败: ' + error).removeClass("success").addClass("error");
2025-12-11 09:17:16 +08:00
}
});
});
2026-01-09 13:45:30 +08:00
// 发送按钮点击事件
2025-12-11 09:17:16 +08:00
$("#send").click(function() {
let is_add_header = $("#isprotocol").prop("checked");
2026-01-09 13:45:30 +08:00
let ccc = $("#content").val().trim();
// 获取选中的模式
let selectedMode = $("input[name='mode']:checked").val();
var listpwsh = [];
// 根据选择的模式处理数据
if (selectedMode === "读取模式") {
var port_1_val = $("#Port_1").val();
if (port_1_val) {
listpwsh.push("01");
listpwsh.push(port_1_val);
}
}
else if (selectedMode === "设置模式") {
var port_2_val = $("#Port_2").val();
var Byte_Speed_v = $("#Byte_Speed").val();
var MoshiID_v = $("#moshi_id").val();
var tm2_v = $("#tm2").val();
if (port_2_val && Byte_Speed_v && MoshiID_v && tm2_v) {
listpwsh.push("02");
listpwsh.push(port_2_val);
listpwsh.push(Byte_Speed_v);
listpwsh.push(tm2_v);
listpwsh.push(MoshiID_v);
}
}
else if (selectedMode === "发送模式") {
if (!ccc) {
$("#result").html('<i class="fas fa-exclamation-circle"></i> 请输入透传内容').removeClass("success").addClass("error");
$("#content").focus();
return;
}
var port_4_val = $("#Port_4").val();
var tm4_val = $("#tm4").val();
if (port_4_val && tm4_val && ccc) {
listpwsh.push("03");
listpwsh.push(port_4_val);
listpwsh.push(tm4_val);
listpwsh.push(ccc);
}
}
var finally_ccc = listpwsh.join(' ');
console.log(finally_ccc);
2025-12-11 09:17:16 +08:00
let hhh = $("#txthostnumber").val();
let mac = "";
2026-01-09 13:45:30 +08:00
let p_type = $("#protocoltype").val() || "70";
2025-12-11 09:17:16 +08:00
let jjj = {
hostnumber: hhh,
mac: mac,
2026-01-09 13:45:30 +08:00
bytelist: finally_ccc,
2025-12-11 09:17:16 +08:00
cmdtype: p_type,
isoriginal: is_add_header
};
2026-01-09 13:45:30 +08:00
2025-12-11 09:17:16 +08:00
$.ajax({
url: '/api/SendUDPPackage',
2026-01-09 13:45:30 +08:00
type: 'POST',
2025-12-11 09:17:16 +08:00
contentType: 'application/x-www-form-urlencoded',
data: jjj,
success: function(response) {
console.log(response);
2026-01-09 13:45:30 +08:00
addMessage(ccc, true);
$("#result").html('<i class="fas fa-check-circle"></i> 发送成功').removeClass("error").addClass("success");
2025-12-11 09:17:16 +08:00
},
error: function(xhr, status, error) {
console.log(error);
2026-01-09 13:45:30 +08:00
$("#result").html('<i class="fas fa-times-circle"></i> 发送失败: ' + error).removeClass("success").addClass("error");
2025-12-11 09:17:16 +08:00
}
});
});
2026-01-09 13:45:30 +08:00
// 清空记录按钮
$("#clear-btn").click(function() {
lastReceivedAtMs = null;
2026-01-09 14:52:58 +08:00
$("#touchuan_tbody").html(`
<tr class="message-row-received">
<td>${getCurrentTime()}</td>
<td>-</td>
<td></td>
<td></td>
<td></td>
<td>记录已清空</td>
<td></td>
</tr>
2026-01-09 13:45:30 +08:00
`);
});
// 输入框回车键支持
$("#txthostnumber, #content").keypress(function(e) {
if (e.which === 13) { // 回车键
e.preventDefault();
if ($(this).attr("id") === "txthostnumber") {
$("#btn_set").click();
} else {
$("#send").click();
}
}
});
// 模式切换时显示/隐藏相关字段
$("input[name='mode']").change(function() {
const selectedMode = $(this).val();
togglePortVisibility(selectedMode);
});
2025-12-11 09:17:16 +08:00
});
</script>
</body>
</html>