1
0

home.wxml 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  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">
  10. <image class="panel-icon-image" src="/assets/icons/bluetooth-connected-white.png" mode="aspectFit" />
  11. </view>
  12. <view class="panel-title">连接状态</view>
  13. <view class="panel-actions connection-actions">
  14. <view
  15. class="panel-action-button {{canStartScan ? '' : 'is-disabled'}}"
  16. bindtap="startScan"
  17. >
  18. {{scanButtonText}}
  19. </view>
  20. <view
  21. class="panel-action-button {{canClearDevices ? '' : 'is-disabled'}}"
  22. bindtap="clearDevices"
  23. >
  24. 清空
  25. </view>
  26. <view
  27. class="panel-action-button {{canDisconnectDevice ? '' : 'is-disabled'}}"
  28. bindtap="disconnectDevice"
  29. >
  30. 断开
  31. </view>
  32. </view>
  33. </view>
  34. <view class="connected-summary">
  35. <view class="connected-name">
  36. {{connectionName}}
  37. </view>
  38. </view>
  39. <view class="device-badges connection-badges">
  40. <view class="traffic-badge">{{txCount}} / {{rxCount}} bytes</view>
  41. <view class="rssi">{{connectionSignalText}}</view>
  42. <view class="connect-state {{connectedDevice ? 'connected' : ''}}">{{connectionStatusText}}</view>
  43. </view>
  44. <view class="meta-grid">
  45. <view class="meta-item">
  46. <text class="meta-label">设备 ID</text>
  47. <text class="meta-value">{{connectionDeviceId}}</text>
  48. </view>
  49. <view class="meta-item">
  50. <text class="meta-label">服务数</text>
  51. <text class="meta-value">{{connectionServiceCount}}</text>
  52. </view>
  53. <view class="meta-item">
  54. <text class="meta-label">特征值</text>
  55. <text class="meta-value">{{connectionCharacteristicText}}</text>
  56. </view>
  57. </view>
  58. </view>
  59. <view wx:if="{{showDeviceSection}}" class="device-section">
  60. <view class="panel-header outside-header">
  61. <view class="panel-icon icon-radar">
  62. <image class="panel-icon-image" src="/assets/icons/radar-white.png" mode="aspectFit" />
  63. </view>
  64. <view class="panel-title">附近设备 {{deviceCountText}}</view>
  65. <view class="device-filter">
  66. <view
  67. wx:for="{{deviceFilterOptions}}"
  68. wx:key="key"
  69. class="device-filter-item {{deviceFilterMode === item.key ? 'is-active' : ''}}"
  70. data-filter="{{item.key}}"
  71. bindtap="onDeviceFilterTap"
  72. >
  73. {{item.label}}
  74. </view>
  75. </view>
  76. </view>
  77. <scroll-view class="device-scroll" scroll-y type="list">
  78. <view wx:if="{{!devices.length}}" class="empty-state">
  79. <view class="empty-title">{{emptyDeviceTitle}}</view>
  80. <view class="empty-text">{{emptyDeviceText}}</view>
  81. </view>
  82. <view
  83. wx:for="{{devices}}"
  84. wx:key="deviceId"
  85. class="device-card {{connectedDevice && connectedDevice.deviceId === item.deviceId ? 'device-card--connected' : ''}}"
  86. data-device-id="{{item.deviceId}}"
  87. bindtap="connectDevice"
  88. >
  89. <view class="device-info">
  90. <view class="device-main-row">
  91. <view class="device-name">{{item.displayName}}</view>
  92. </view>
  93. <view class="device-badges device-badges--stacked">
  94. <view wx:if="{{connectingDeviceId === item.deviceId}}" class="connect-state">连接中</view>
  95. <view wx:elif="{{connectedDevice && connectedDevice.deviceId === item.deviceId}}" class="connect-state connected">已连接</view>
  96. <view wx:else class="connect-state">连接</view>
  97. <view class="rssi">{{item.signalText}}</view>
  98. </view>
  99. <view class="device-id">{{item.deviceId}}</view>
  100. <view class="device-meta-row">
  101. <view class="device-service">{{item.serviceText}}</view>
  102. <view wx:if="{{item.targetText}}" class="device-target">{{item.targetText}}</view>
  103. </view>
  104. </view>
  105. </view>
  106. </scroll-view>
  107. </view>
  108. <view class="panel">
  109. <view class="panel-header panel-header--with-actions">
  110. <view class="panel-icon icon-terminal">
  111. <image class="panel-icon-image" src="/assets/icons/terminal-white.png" mode="aspectFit" />
  112. </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">
  197. <image class="panel-icon-image" src="/assets/icons/send-white.png" mode="aspectFit" />
  198. </view>
  199. <view class="panel-title">发送</view>
  200. <view class="panel-actions">
  201. <view class="panel-action-button" bindtap="clearInput">清空</view>
  202. <view
  203. class="panel-action-button {{!connectedDevice ? 'is-disabled' : ''}}"
  204. bindtap="sendHexFrame"
  205. >
  206. 发送
  207. </view>
  208. </view>
  209. </view>
  210. <textarea
  211. class="hex-input"
  212. maxlength="-1"
  213. auto-height
  214. placeholder="例如:01 03 00 00 00 01 84 0A"
  215. value="{{sendHex}}"
  216. bindinput="onHexInput"
  217. />
  218. </view>
  219. <view class="panel">
  220. <view class="panel-header panel-header--with-actions log-header">
  221. <view class="panel-icon icon-history">
  222. <image class="panel-icon-image" src="/assets/icons/history-white.png" mode="aspectFit" />
  223. </view>
  224. <view class="panel-title">收发日志 {{logs.length ? '(' + logs.length + ')' : ''}}</view>
  225. <view class="panel-actions">
  226. <view class="panel-action-button" bindtap="clearLogs">清空</view>
  227. </view>
  228. </view>
  229. <scroll-view
  230. class="log-scroll"
  231. scroll-y
  232. scroll-with-animation
  233. scroll-into-view="{{logScrollTarget}}"
  234. type="list"
  235. >
  236. <view wx:if="{{!logs.length}}" class="empty-log">暂无收发数据</view>
  237. <view
  238. wx:for="{{logs}}"
  239. wx:key="id"
  240. id="{{item.id}}"
  241. class="log-row log-row--{{item.direction}}"
  242. >
  243. <view class="log-meta">
  244. <view class="log-tags">
  245. <text class="log-direction">{{item.direction}}</text>
  246. <text wx:if="{{item.note}}" class="log-note">{{item.note}}</text>
  247. </view>
  248. <text class="log-time">{{item.time}}</text>
  249. </view>
  250. <view class="log-payload">{{item.payload}}</view>
  251. </view>
  252. </scroll-view>
  253. </view>
  254. </view>
  255. </scroll-view>
  256. <view wx:if="{{protocolMultipleDialog.visible}}" class="generic-dialog-mask {{themeClass}}" bindtap="closeProtocolMultipleDialog">
  257. <view class="generic-dialog protocol-multiple-dialog" catchtap="noop">
  258. <view class="generic-dialog-header">
  259. <view class="generic-dialog-title">{{protocolMultipleDialog.title}}</view>
  260. <view class="generic-dialog-close" bindtap="closeProtocolMultipleDialog">×</view>
  261. </view>
  262. <view class="generic-dialog-body">
  263. <view
  264. wx:for="{{protocolMultipleValues}}"
  265. wx:for-item="register"
  266. wx:for-index="registerIndex"
  267. wx:key="id"
  268. class="protocol-multiple-row"
  269. >
  270. <view class="protocol-multiple-head">
  271. <view class="protocol-multiple-title">{{register.addressText}}</view>
  272. <picker
  273. mode="selector"
  274. range="{{protocolDataTypeOptions}}"
  275. range-key="label"
  276. value="{{register.dataTypeIndex}}"
  277. data-index="{{registerIndex}}"
  278. bindchange="onProtocolMultipleTypeChange"
  279. >
  280. <view class="generic-picker-value protocol-multiple-type">{{register.dataTypeText}}</view>
  281. </picker>
  282. </view>
  283. <view wx:if="{{register.showTextLength}}" class="protocol-multiple-text-length">
  284. <text class="param-meta">长度</text>
  285. <input
  286. class="value-input protocol-multiple-length-input"
  287. type="number"
  288. data-index="{{registerIndex}}"
  289. value="{{register.textByteLength}}"
  290. bindinput="onProtocolMultipleTextLengthInput"
  291. />
  292. </view>
  293. <input
  294. class="value-input protocol-multiple-input {{register.showTextLength ? 'protocol-multiple-input--text' : ''}}"
  295. placeholder="{{register.dataTypeText}}"
  296. data-index="{{registerIndex}}"
  297. value="{{register.inputValue}}"
  298. bindinput="onProtocolMultipleValueInput"
  299. bindblur="onProtocolMultipleValueBlur"
  300. />
  301. </view>
  302. </view>
  303. <view class="generic-draft-actions">
  304. <view class="panel-action-button is-active" bindtap="closeProtocolMultipleDialog">确认</view>
  305. </view>
  306. </view>
  307. </view>