| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314 |
- <navigation-bar background="{{themeMode === 'dark' ? '#111827' : '#FFF'}}"></navigation-bar>
- <view wx:if="{{toastText}}" class="page-toast page-toast--{{toastType}} {{themeClass}}">
- {{toastText}}
- </view>
- <scroll-view class="scrollarea {{themeClass}}" scroll-y type="list">
- <view class="page-shell">
- <view class="connected-panel">
- <view class="panel-header panel-header--with-actions">
- <view class="panel-icon icon-bluetooth">
- <image class="panel-icon-image" src="/assets/icons/bluetooth-connected-white.png" mode="aspectFit" />
- </view>
- <view class="panel-title">连接状态</view>
- <view class="panel-actions connection-actions">
- <view
- class="panel-action-button {{canStartScan ? '' : 'is-disabled'}}"
- bindtap="startScan"
- >
- {{scanButtonText}}
- </view>
- <view
- class="panel-action-button {{canClearDevices ? '' : 'is-disabled'}}"
- bindtap="clearDevices"
- >
- 清空
- </view>
- <view
- class="panel-action-button {{canDisconnectDevice ? '' : 'is-disabled'}}"
- bindtap="disconnectDevice"
- >
- 断开
- </view>
- </view>
- </view>
- <view class="connected-summary">
- <view class="connected-name">
- {{connectionName}}
- </view>
- </view>
- <view class="device-badges connection-badges">
- <view class="traffic-badge">{{txCount}} / {{rxCount}} bytes</view>
- <view class="rssi">{{connectionSignalText}}</view>
- <view class="connect-state {{connectedDevice ? 'connected' : ''}}">{{connectionStatusText}}</view>
- </view>
- <view class="meta-grid">
- <view class="meta-item">
- <text class="meta-label">设备 ID</text>
- <text class="meta-value">{{connectionDeviceId}}</text>
- </view>
- <view class="meta-item">
- <text class="meta-label">服务数</text>
- <text class="meta-value">{{connectionServiceCount}}</text>
- </view>
- <view class="meta-item">
- <text class="meta-label">特征值</text>
- <text class="meta-value">{{connectionCharacteristicText}}</text>
- </view>
- </view>
- </view>
- <view wx:if="{{showDeviceSection}}" class="device-section">
- <view class="panel-header outside-header">
- <view class="panel-icon icon-radar">
- <image class="panel-icon-image" src="/assets/icons/radar-white.png" mode="aspectFit" />
- </view>
- <view class="panel-title">附近设备 {{deviceCountText}}</view>
- <view class="device-filter">
- <view
- wx:for="{{deviceFilterOptions}}"
- wx:key="key"
- class="device-filter-item {{deviceFilterMode === item.key ? 'is-active' : ''}}"
- data-filter="{{item.key}}"
- bindtap="onDeviceFilterTap"
- >
- {{item.label}}
- </view>
- </view>
- </view>
- <scroll-view class="device-scroll" scroll-y type="list">
- <view wx:if="{{!devices.length}}" class="empty-state">
- <view class="empty-title">{{emptyDeviceTitle}}</view>
- <view class="empty-text">{{emptyDeviceText}}</view>
- </view>
- <view
- wx:for="{{devices}}"
- wx:key="deviceId"
- class="device-card {{connectedDevice && connectedDevice.deviceId === item.deviceId ? 'device-card--connected' : ''}}"
- data-device-id="{{item.deviceId}}"
- bindtap="connectDevice"
- >
- <view class="device-info">
- <view class="device-main-row">
- <view class="device-name">{{item.displayName}}</view>
- </view>
- <view class="device-badges device-badges--stacked">
- <view wx:if="{{connectingDeviceId === item.deviceId}}" class="connect-state">连接中</view>
- <view wx:elif="{{connectedDevice && connectedDevice.deviceId === item.deviceId}}" class="connect-state connected">已连接</view>
- <view wx:else class="connect-state">连接</view>
- <view class="rssi">{{item.signalText}}</view>
- </view>
- <view class="device-id">{{item.deviceId}}</view>
- <view class="device-meta-row">
- <view class="device-service">{{item.serviceText}}</view>
- <view wx:if="{{item.targetText}}" class="device-target">{{item.targetText}}</view>
- </view>
- </view>
- </view>
- </scroll-view>
- </view>
- <view class="panel">
- <view class="panel-header panel-header--with-actions">
- <view class="panel-icon icon-terminal">
- <image class="panel-icon-image" src="/assets/icons/terminal-white.png" mode="aspectFit" />
- </view>
- <view class="panel-title">Modbus RTU 指令</view>
- <view class="panel-actions">
- <view
- class="panel-action-button {{!connectedDevice || !generatedHex ? 'is-disabled' : ''}}"
- bindtap="sendGeneratedFrame"
- >
- 下发
- </view>
- </view>
- </view>
- <view class="protocol-form">
- <view class="protocol-row">
- <text class="protocol-label">功能码</text>
- <picker
- class="protocol-picker"
- mode="selector"
- range="{{protocolCommands}}"
- range-key="label"
- value="{{commandIndex}}"
- bindchange="onCommandChange"
- >
- <view class="picker-value">{{protocolCommands[commandIndex].label}}</view>
- </picker>
- </view>
- <view class="protocol-row protocol-field-row">
- <text class="protocol-label">从站地址</text>
- <input
- class="protocol-input protocol-row-input"
- type="text"
- maxlength="2"
- value="{{slaveAddress}}"
- bindinput="onSlaveAddressInput"
- />
- </view>
- <view class="protocol-row protocol-field-row">
- <text class="protocol-label">起始地址</text>
- <input
- class="protocol-input protocol-row-input"
- type="text"
- maxlength="4"
- value="{{registerAddress}}"
- bindinput="onRegisterAddressInput"
- />
- </view>
- <view wx:if="{{showRegisterQuantity}}" class="protocol-row protocol-field-row">
- <text class="protocol-label">寄存器个数</text>
- <input
- class="protocol-input protocol-row-input"
- type="text"
- maxlength="4"
- value="{{commandRegisterQuantity}}"
- bindinput="onCommandRegisterQuantityInput"
- />
- </view>
- <view wx:if="{{showCommandValue}}" class="protocol-row protocol-field-row">
- <text class="protocol-label">{{commandValueLabel}}</text>
- <view wx:if="{{showRegisterQuantity}}" class="protocol-input protocol-row-input protocol-value-picker" bindtap="openProtocolMultipleDialog">
- {{commandValue || '点击编辑'}}
- </view>
- <input
- wx:else
- class="protocol-input protocol-row-input"
- type="text"
- value="{{commandValue}}"
- bindinput="onCommandValueInput"
- />
- </view>
- <view wx:if="{{showCoilValue}}" class="protocol-row coil-row">
- <text class="protocol-label">线圈值</text>
- <view class="coil-control">
- <text>{{coilEnabled ? 'ON' : 'OFF'}}</text>
- <switch checked="{{coilEnabled}}" color="#0f766e" bindchange="onCoilValueChange" />
- </view>
- </view>
- <view class="generated-frame">
- <view class="generated-title">生成帧</view>
- <view class="generated-value">{{generatedHex || '--'}}</view>
- <view wx:if="{{protocolErrorText}}" class="protocol-error">{{protocolErrorText}}</view>
- </view>
- </view>
- </view>
- <view class="panel">
- <view class="panel-header panel-header--with-actions">
- <view class="panel-icon icon-send">
- <image class="panel-icon-image" src="/assets/icons/send-white.png" mode="aspectFit" />
- </view>
- <view class="panel-title">发送</view>
- <view class="panel-actions">
- <view class="panel-action-button" bindtap="clearInput">清空</view>
- <view
- class="panel-action-button {{!connectedDevice ? 'is-disabled' : ''}}"
- bindtap="sendHexFrame"
- >
- 发送
- </view>
- </view>
- </view>
- <textarea
- class="hex-input"
- maxlength="-1"
- auto-height
- placeholder="例如:01 03 00 00 00 01 84 0A"
- value="{{sendHex}}"
- bindinput="onHexInput"
- />
- </view>
- <view class="panel">
- <view class="panel-header panel-header--with-actions log-header">
- <view class="panel-icon icon-history">
- <image class="panel-icon-image" src="/assets/icons/history-white.png" mode="aspectFit" />
- </view>
- <view class="panel-title">收发日志 {{logs.length ? '(' + logs.length + ')' : ''}}</view>
- <view class="panel-actions">
- <view class="panel-action-button" bindtap="clearLogs">清空</view>
- </view>
- </view>
- <scroll-view
- class="log-scroll"
- scroll-y
- scroll-with-animation
- scroll-into-view="{{logScrollTarget}}"
- type="list"
- >
- <view wx:if="{{!logs.length}}" class="empty-log">暂无收发数据</view>
- <view
- wx:for="{{logs}}"
- wx:key="id"
- id="{{item.id}}"
- class="log-row log-row--{{item.direction}}"
- >
- <view class="log-meta">
- <view class="log-tags">
- <text class="log-direction">{{item.direction}}</text>
- <text wx:if="{{item.note}}" class="log-note">{{item.note}}</text>
- </view>
- <text class="log-time">{{item.time}}</text>
- </view>
- <view class="log-payload">{{item.payload}}</view>
- </view>
- </scroll-view>
- </view>
- </view>
- </scroll-view>
- <view wx:if="{{protocolMultipleDialog.visible}}" class="generic-dialog-mask {{themeClass}}" bindtap="closeProtocolMultipleDialog">
- <view class="generic-dialog protocol-multiple-dialog" catchtap="noop">
- <view class="generic-dialog-header">
- <view class="generic-dialog-title">{{protocolMultipleDialog.title}}</view>
- <view class="generic-dialog-close" bindtap="closeProtocolMultipleDialog">×</view>
- </view>
- <view class="generic-dialog-body">
- <view
- wx:for="{{protocolMultipleValues}}"
- wx:for-item="register"
- wx:for-index="registerIndex"
- wx:key="id"
- class="protocol-multiple-row"
- >
- <view class="protocol-multiple-head">
- <view class="protocol-multiple-title">{{register.addressText}}</view>
- <picker
- mode="selector"
- range="{{protocolDataTypeOptions}}"
- range-key="label"
- value="{{register.dataTypeIndex}}"
- data-index="{{registerIndex}}"
- bindchange="onProtocolMultipleTypeChange"
- >
- <view class="generic-picker-value protocol-multiple-type">{{register.dataTypeText}}</view>
- </picker>
- </view>
- <view wx:if="{{register.showTextLength}}" class="protocol-multiple-text-length">
- <text class="param-meta">长度</text>
- <input
- class="value-input protocol-multiple-length-input"
- type="number"
- data-index="{{registerIndex}}"
- value="{{register.textByteLength}}"
- bindinput="onProtocolMultipleTextLengthInput"
- />
- </view>
- <input
- class="value-input protocol-multiple-input {{register.showTextLength ? 'protocol-multiple-input--text' : ''}}"
- placeholder="{{register.dataTypeText}}"
- data-index="{{registerIndex}}"
- value="{{register.inputValue}}"
- bindinput="onProtocolMultipleValueInput"
- bindblur="onProtocolMultipleValueBlur"
- />
- </view>
- </view>
- <view class="generic-draft-actions">
- <view class="panel-action-button is-active" bindtap="closeProtocolMultipleDialog">确认</view>
- </view>
- </view>
- </view>
|