home.wxml 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. <navigation-bar background="{{themeMode === 'dark' ? '#111827' : '#FFF'}}"></navigation-bar>
  2. <view wx:if="{{toastText}}" class="page-toast page-toast--{{toastType}} {{themeClass}}">
  3. {{toastText}}
  4. </view>
  5. <scroll-view class="scrollarea {{themeClass}}" scroll-y type="list">
  6. <view class="page-shell">
  7. <view class="connected-panel">
  8. <view class="panel-header panel-header--with-actions">
  9. <view class="panel-icon icon-bluetooth"></view>
  10. <view class="panel-title">连接状态</view>
  11. <view class="panel-actions connection-actions">
  12. <view
  13. class="panel-action-button {{canSyncRegisters ? '' : 'is-disabled'}}"
  14. bindtap="syncRegisters"
  15. >
  16. 同步
  17. </view>
  18. <view
  19. class="panel-action-button {{canStartScan ? '' : 'is-disabled'}}"
  20. bindtap="startScan"
  21. >
  22. {{scanButtonText}}
  23. </view>
  24. <view
  25. class="panel-action-button {{canClearDevices ? '' : 'is-disabled'}}"
  26. bindtap="clearDevices"
  27. >
  28. 清空
  29. </view>
  30. <view
  31. class="panel-action-button {{canDisconnectDevice ? '' : 'is-disabled'}}"
  32. bindtap="disconnectDevice"
  33. >
  34. 断开
  35. </view>
  36. </view>
  37. </view>
  38. <view class="connected-summary">
  39. <view class="connected-name">
  40. {{connectionName}}
  41. </view>
  42. </view>
  43. <view class="device-badges connection-badges">
  44. <view class="traffic-badge">{{txCount}} / {{rxCount}} bytes</view>
  45. <view class="rssi">{{connectionSignalText}}</view>
  46. <view class="connect-state {{connectedDevice ? 'connected' : ''}}">{{connectionStatusText}}</view>
  47. </view>
  48. <view class="meta-grid">
  49. <view class="meta-item">
  50. <text class="meta-label">设备 ID</text>
  51. <text class="meta-value">{{connectionDeviceId}}</text>
  52. </view>
  53. <view class="meta-item">
  54. <text class="meta-label">服务数</text>
  55. <text class="meta-value">{{connectionServiceCount}}</text>
  56. </view>
  57. <view class="meta-item">
  58. <text class="meta-label">特征值</text>
  59. <text class="meta-value">{{connectionCharacteristicText}}</text>
  60. </view>
  61. </view>
  62. </view>
  63. <view wx:if="{{showDeviceSection}}" class="device-section">
  64. <view class="panel-header outside-header">
  65. <view class="panel-icon icon-radar"></view>
  66. <view class="panel-title">附近设备 {{deviceCountText}}</view>
  67. <view class="device-filter">
  68. <view
  69. wx:for="{{deviceFilterOptions}}"
  70. wx:key="key"
  71. class="device-filter-item {{deviceFilterMode === item.key ? 'is-active' : ''}}"
  72. data-filter="{{item.key}}"
  73. bindtap="onDeviceFilterTap"
  74. >
  75. {{item.label}}
  76. </view>
  77. </view>
  78. </view>
  79. <scroll-view class="device-scroll" scroll-y type="list">
  80. <view wx:if="{{!devices.length}}" class="empty-state">
  81. <view class="empty-title">{{emptyDeviceTitle}}</view>
  82. <view class="empty-text">{{emptyDeviceText}}</view>
  83. </view>
  84. <view
  85. wx:for="{{devices}}"
  86. wx:key="deviceId"
  87. class="device-card {{connectedDevice && connectedDevice.deviceId === item.deviceId ? 'device-card--connected' : ''}}"
  88. data-device-id="{{item.deviceId}}"
  89. bindtap="connectDevice"
  90. >
  91. <view class="device-info">
  92. <view class="device-main-row">
  93. <view class="device-name">{{item.displayName}}</view>
  94. </view>
  95. <view class="device-badges device-badges--stacked">
  96. <view wx:if="{{connectingDeviceId === item.deviceId}}" class="connect-state">连接中</view>
  97. <view wx:elif="{{connectedDevice && connectedDevice.deviceId === item.deviceId}}" class="connect-state connected">已连接</view>
  98. <view wx:else class="connect-state">连接</view>
  99. <view class="rssi">{{item.signalText}}</view>
  100. </view>
  101. <view class="device-id">{{item.deviceId}}</view>
  102. <view class="device-meta-row">
  103. <view class="device-service">{{item.serviceText}}</view>
  104. <view wx:if="{{item.targetText}}" class="device-target">{{item.targetText}}</view>
  105. </view>
  106. </view>
  107. </view>
  108. </scroll-view>
  109. </view>
  110. <view class="panel">
  111. <view class="panel-header panel-header--with-actions">
  112. <view class="panel-icon icon-terminal"></view>
  113. <view class="panel-title">Modbus RTU 指令</view>
  114. <view class="panel-actions">
  115. <view
  116. class="panel-action-button {{!connectedDevice || !generatedHex ? 'is-disabled' : ''}}"
  117. bindtap="sendGeneratedFrame"
  118. >
  119. 下发
  120. </view>
  121. </view>
  122. </view>
  123. <view class="protocol-form">
  124. <view class="protocol-row">
  125. <text class="protocol-label">功能码</text>
  126. <picker
  127. class="protocol-picker"
  128. mode="selector"
  129. range="{{protocolCommands}}"
  130. range-key="label"
  131. value="{{commandIndex}}"
  132. bindchange="onCommandChange"
  133. >
  134. <view class="picker-value">{{protocolCommands[commandIndex].label}}</view>
  135. </picker>
  136. </view>
  137. <view class="protocol-row protocol-field-row">
  138. <text class="protocol-label">从站地址</text>
  139. <input
  140. class="protocol-input protocol-row-input"
  141. type="text"
  142. maxlength="2"
  143. value="{{slaveAddress}}"
  144. bindinput="onSlaveAddressInput"
  145. />
  146. </view>
  147. <view class="protocol-row protocol-field-row">
  148. <text class="protocol-label">起始地址</text>
  149. <input
  150. class="protocol-input protocol-row-input"
  151. type="text"
  152. maxlength="4"
  153. value="{{registerAddress}}"
  154. bindinput="onRegisterAddressInput"
  155. />
  156. </view>
  157. <view wx:if="{{showRegisterQuantity}}" class="protocol-row protocol-field-row">
  158. <text class="protocol-label">寄存器个数</text>
  159. <input
  160. class="protocol-input protocol-row-input"
  161. type="text"
  162. maxlength="4"
  163. value="{{commandRegisterQuantity}}"
  164. bindinput="onCommandRegisterQuantityInput"
  165. />
  166. </view>
  167. <view wx:if="{{showCommandValue}}" class="protocol-row protocol-field-row">
  168. <text class="protocol-label">{{commandValueLabel}}</text>
  169. <view wx:if="{{showRegisterQuantity}}" class="protocol-input protocol-row-input protocol-value-picker" bindtap="openProtocolMultipleDialog">
  170. {{commandValue || '点击编辑'}}
  171. </view>
  172. <input
  173. wx:else
  174. class="protocol-input protocol-row-input"
  175. type="text"
  176. value="{{commandValue}}"
  177. bindinput="onCommandValueInput"
  178. />
  179. </view>
  180. <view wx:if="{{showCoilValue}}" class="protocol-row coil-row">
  181. <text class="protocol-label">线圈值</text>
  182. <view class="coil-control">
  183. <text>{{coilEnabled ? 'ON' : 'OFF'}}</text>
  184. <switch checked="{{coilEnabled}}" color="#0f766e" bindchange="onCoilValueChange" />
  185. </view>
  186. </view>
  187. <view class="generated-frame">
  188. <view class="generated-title">生成帧</view>
  189. <view class="generated-value">{{generatedHex || '--'}}</view>
  190. <view wx:if="{{protocolErrorText}}" class="protocol-error">{{protocolErrorText}}</view>
  191. </view>
  192. </view>
  193. </view>
  194. <view class="panel">
  195. <view class="panel-header panel-header--with-actions">
  196. <view class="panel-icon icon-send"></view>
  197. <view class="panel-title">发送</view>
  198. <view class="panel-actions">
  199. <view class="panel-action-button" bindtap="clearInput">清空</view>
  200. <view
  201. class="panel-action-button {{!connectedDevice ? 'is-disabled' : ''}}"
  202. bindtap="sendHexFrame"
  203. >
  204. 发送
  205. </view>
  206. </view>
  207. </view>
  208. <textarea
  209. class="hex-input"
  210. maxlength="-1"
  211. auto-height
  212. placeholder="例如:01 03 00 00 00 01 84 0A"
  213. value="{{sendHex}}"
  214. bindinput="onHexInput"
  215. />
  216. </view>
  217. <view class="panel">
  218. <view class="panel-header panel-header--with-actions log-header">
  219. <view class="panel-icon icon-history"></view>
  220. <view class="panel-title">收发日志 {{logs.length ? '(' + logs.length + ')' : ''}}</view>
  221. <view class="panel-actions">
  222. <view class="panel-action-button" bindtap="clearLogs">清空</view>
  223. </view>
  224. </view>
  225. <scroll-view
  226. class="log-scroll"
  227. scroll-y
  228. scroll-with-animation
  229. scroll-into-view="{{logScrollTarget}}"
  230. type="list"
  231. >
  232. <view wx:if="{{!logs.length}}" class="empty-log">暂无收发数据</view>
  233. <view
  234. wx:for="{{logs}}"
  235. wx:key="id"
  236. id="{{item.id}}"
  237. class="log-row log-row--{{item.direction}}"
  238. >
  239. <view class="log-meta">
  240. <view class="log-tags">
  241. <text class="log-direction">{{item.direction}}</text>
  242. <text wx:if="{{item.note}}" class="log-note">{{item.note}}</text>
  243. </view>
  244. <text class="log-time">{{item.time}}</text>
  245. </view>
  246. <view class="log-payload">{{item.payload}}</view>
  247. </view>
  248. </scroll-view>
  249. </view>
  250. </view>
  251. </scroll-view>
  252. <view wx:if="{{protocolMultipleDialog.visible}}" class="generic-dialog-mask {{themeClass}}" bindtap="closeProtocolMultipleDialog">
  253. <view class="generic-dialog protocol-multiple-dialog" catchtap="noop">
  254. <view class="generic-dialog-header">
  255. <view class="generic-dialog-title">{{protocolMultipleDialog.title}}</view>
  256. <view class="generic-dialog-close" bindtap="closeProtocolMultipleDialog">×</view>
  257. </view>
  258. <view class="generic-dialog-body">
  259. <view
  260. wx:for="{{protocolMultipleValues}}"
  261. wx:for-item="register"
  262. wx:for-index="registerIndex"
  263. wx:key="id"
  264. class="protocol-multiple-row"
  265. >
  266. <view class="protocol-multiple-head">
  267. <view class="protocol-multiple-title">{{register.addressText}}</view>
  268. <picker
  269. mode="selector"
  270. range="{{protocolDataTypeOptions}}"
  271. range-key="label"
  272. value="{{register.dataTypeIndex}}"
  273. data-index="{{registerIndex}}"
  274. bindchange="onProtocolMultipleTypeChange"
  275. >
  276. <view class="generic-picker-value protocol-multiple-type">{{register.dataTypeText}}</view>
  277. </picker>
  278. </view>
  279. <view wx:if="{{register.showTextLength}}" class="protocol-multiple-text-length">
  280. <text class="param-meta">长度</text>
  281. <input
  282. class="value-input protocol-multiple-length-input"
  283. type="number"
  284. data-index="{{registerIndex}}"
  285. value="{{register.textByteLength}}"
  286. bindinput="onProtocolMultipleTextLengthInput"
  287. />
  288. </view>
  289. <input
  290. class="value-input protocol-multiple-input {{register.showTextLength ? 'protocol-multiple-input--text' : ''}}"
  291. placeholder="{{register.dataTypeText}}"
  292. data-index="{{registerIndex}}"
  293. value="{{register.inputValue}}"
  294. bindinput="onProtocolMultipleValueInput"
  295. bindblur="onProtocolMultipleValueBlur"
  296. />
  297. </view>
  298. </view>
  299. <view class="generic-draft-actions">
  300. <view class="panel-action-button is-active" bindtap="closeProtocolMultipleDialog">确认</view>
  301. </view>
  302. </view>
  303. </view>