record.vue 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407
  1. <template>
  2. <view class="container">
  3. <!-- 头部区域 -->
  4. <BluetoothHeader
  5. @ble-data-received="handleBleDataReceived"
  6. />
  7. <view class="main-content">
  8. <!-- 接收窗口 -->
  9. <view class="receive-section">
  10. <text class="section-title">接收窗口</text>
  11. <view class="receive-window">
  12. <scroll-view scroll-y="true" class="receive-textarea">
  13. <view
  14. v-for="(log, index) in sortedWriteLogs"
  15. :key="index"
  16. class="log-item"
  17. >
  18. <view class="log-time">{{log.time}}{{log.data}}</view>
  19. </view>
  20. </scroll-view>
  21. </view>
  22. </view>
  23. <!-- 输入控制区域 -->
  24. <view class="input-section">
  25. <u-row customStyle="margin-bottom: 10px" gutter="10">
  26. <u-col span="8">
  27. <u-input
  28. v-model="inputValue"
  29. placeholder="输入指令"
  30. class="command-input"
  31. ></u-input>
  32. </u-col>
  33. <u-col span="4">
  34. <u-checkbox-group
  35. placement="column">
  36. <u-checkbox v-model="cmdChecked" label="cmd" @change="changeCmd"></u-checkbox>
  37. </u-checkbox-group>
  38. </u-col>
  39. </u-row>
  40. <!-- 操作按钮 -->
  41. <u-row justify="end" customStyle="margin-bottom: 10px">
  42. <u-col span="4">
  43. <u-button type="info" size="mini" class="write-btn" @click="sendMsg">指令发送</u-button>
  44. </u-col>
  45. </u-row>
  46. <u-row customStyle="margin-bottom: 10px" gutter="10">
  47. <u-col span="6">
  48. <u-button text="清空发送" @click="removeLogsByType('rx')"></u-button>
  49. </u-col>
  50. <u-col span="6">
  51. <u-button text="清空接受" @click="removeLogsByType('tx')"></u-button>
  52. </u-col>
  53. </u-row>
  54. </view>
  55. </view>
  56. <DeviceStatusInfo/>
  57. </view>
  58. </template>
  59. <script>
  60. import ecBLEApp from '@/utils/ecBLE/ecBLEApp.js';
  61. import {getAgreement} from '@/utils/modbus.js';
  62. import BluetoothHeader from '@/pages/components/header.vue';
  63. import DeviceStatusInfo from '@/pages/components/DeviceStatusInfo.vue';
  64. export default {
  65. components: {BluetoothHeader,DeviceStatusInfo},
  66. data() {
  67. return {
  68. agreementTypeName:'',
  69. communicationLink: false,
  70. communicationTimer_3: null, // 添加这一行用于保存定时器 ID
  71. writeLogs: [],
  72. showSex: false,
  73. checkboxValue1: [],
  74. inputValue: '',
  75. cmdChecked: false,
  76. carriageReturnChecked: false,
  77. wtypeValue: '',
  78. wtypeChecked: false,
  79. componentType: '单面',
  80. activeTab: 'receive',
  81. componentList: [
  82. { name: '单面'},
  83. { name: '双面'},
  84. { name: '多面'}
  85. ]
  86. }
  87. },
  88. onShow() {
  89. // 从全局变量加载日志
  90. this.writeLogs = ecBLEApp.getGlobalWriteLogs()
  91. // 添加监听器以实时更新
  92. ecBLEApp.addLogListener(this.onLogUpdate);
  93. this.agreementTypeName = getAgreement();
  94. },
  95. onHide() {
  96. // 移除监听器
  97. ecBLEApp.removeLogListener(this.onLogUpdate)
  98. },
  99. computed: {
  100. // 修改排序计算属性
  101. sortedWriteLogs() {
  102. return this.writeLogs.slice().sort((a, b) => {
  103. return new Date(b.time) - new Date(a.time); // 倒序排列
  104. });
  105. }
  106. },
  107. methods: {
  108. // 处理从子组件传递过来的蓝牙数据
  109. handleBleDataReceived(data) {
  110. console.log('在父组件中接收到蓝牙数据:', data);
  111. this.updateSensorData(data);
  112. },
  113. updateSensorData(data) {
  114. },
  115. sendMsg(){
  116. uni.showModal({
  117. title: '提示',
  118. content: `是否确定发送消息`+this.inputValue+`?`,
  119. success: (res) => {
  120. if (res.confirm) {
  121. ecBLEApp.writeBLECharacteristicValueTwo(this.inputValue,!this.cmdChecked);
  122. }
  123. }
  124. });
  125. },
  126. changeCmd(e) {
  127. this.cmdChecked = e
  128. },
  129. changeWtype(e){
  130. this.wtypeChecked = e
  131. },
  132. // 日志更新回调
  133. onLogUpdate(logs) {
  134. // this.writeLogs = [...logs] // 创建新数组以触发响应式更新
  135. this.writeLogs.splice(0, this.writeLogs.length, ...logs)
  136. },
  137. loadLogs() {
  138. // 从全局变量获取日志
  139. const newLogs = ecBLEApp.getGlobalWriteLogs()
  140. // 使用数组变更方法保持响应式
  141. this.writeLogs.splice(0, this.writeLogs.length, ...newLogs)
  142. },
  143. selectValue(e) {
  144. this.componentType = e.name
  145. },
  146. switchTab(tab) {
  147. this.activeTab = tab;
  148. },
  149. sendCommand() {
  150. // 发送指令逻辑
  151. console.log('发送指令:', this.inputValue);
  152. },
  153. writeType() {
  154. // 类型写入逻辑
  155. console.log('写入类型:', this.wtypeValue);
  156. },
  157. clearSend() {
  158. this.inputValue = '';
  159. },
  160. clearReceive() {
  161. // 清空接收窗口
  162. console.log('清空接收窗口');
  163. },
  164. removeLogsByType(type) {
  165. uni.showModal({
  166. title: '确认删除',
  167. content: `确定要删除所有类型为 '${type}' 的日志吗?`,
  168. success: (res) => {
  169. if (res.confirm) {
  170. const result = ecBLEApp.removeWriteDataByType(type)
  171. if (result.success) {
  172. uni.showToast({
  173. title: `已删除${result.deletedCount}条日志`,
  174. icon: 'success'
  175. })
  176. // 重新加载日志
  177. this.loadLogs();
  178. console.log('删除日志结果:', result)
  179. console.log(this.writeLogs)
  180. } else {
  181. uni.showToast({
  182. title: '删除失败',
  183. icon: 'none'
  184. })
  185. }
  186. }
  187. }
  188. })
  189. },
  190. }
  191. }
  192. </script>
  193. <style lang="scss" >
  194. @import '@/static/scss/custom-theme.scss';
  195. .container {
  196. height: calc(100vh - 120px);
  197. display: flex;
  198. flex-direction: column;
  199. background-color: #f5f5f5;
  200. }
  201. .status-bar {
  202. height: 60rpx;
  203. background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  204. display: flex;
  205. align-items: center;
  206. justify-content: space-between;
  207. padding: 0 20rpx;
  208. color: white;
  209. font-size: 24rpx;
  210. }
  211. .status-left {
  212. display: flex;
  213. align-items: center;
  214. gap: 20rpx;
  215. }
  216. .status-center {
  217. flex: 1;
  218. text-align: center;
  219. }
  220. .app-title {
  221. font-size: 32rpx;
  222. font-weight: bold;
  223. }
  224. .status-right {
  225. display: flex;
  226. align-items: center;
  227. gap: 10rpx;
  228. }
  229. .network-info {
  230. font-size: 20rpx;
  231. }
  232. .signal {
  233. font-size: 20rpx;
  234. }
  235. .signal-bars {
  236. display: flex;
  237. gap: 2rpx;
  238. }
  239. .bar {
  240. width: 4rpx;
  241. height: 12rpx;
  242. background-color: white;
  243. border-radius: 1rpx;
  244. }
  245. .battery {
  246. font-size: 20rpx;
  247. }
  248. .main-content {
  249. flex: 1;
  250. padding: 20rpx;
  251. background-color: #f5f5f5;
  252. height: calc(100% - 140rpx);
  253. }
  254. .receive-section {
  255. margin-bottom: 30rpx;
  256. }
  257. .section-title {
  258. font-size: 28rpx;
  259. font-weight: bold;
  260. color: #333;
  261. margin-bottom: 10rpx;
  262. display: block;
  263. }
  264. .receive-window {
  265. background-color: white;
  266. border-radius: 10rpx;
  267. border: 2rpx solid #e0e0e0;
  268. height: 40vh;
  269. overflow: auto;
  270. }
  271. .receive-textarea {
  272. height: 100%;
  273. padding: 20rpx;
  274. }
  275. .placeholder-text {
  276. color: #999;
  277. font-size: 24rpx;
  278. }
  279. .input-section {
  280. background-color: white;
  281. border-radius: 10rpx;
  282. padding: 20rpx;
  283. }
  284. .input-row {
  285. display: flex;
  286. align-items: center;
  287. margin-bottom: 20rpx;
  288. gap: 20rpx;
  289. }
  290. .input-group {
  291. display: flex;
  292. align-items: center;
  293. flex: 1;
  294. gap: 10rpx;
  295. }
  296. .command-input, .wtype-input {
  297. flex: 1;
  298. }
  299. .scroll-btn {
  300. width: 60rpx;
  301. height: 60rpx;
  302. }
  303. .checkbox-group {
  304. display: flex;
  305. align-items: center;
  306. }
  307. .send-btn {
  308. width: 120rpx;
  309. }
  310. .component-section {
  311. margin-bottom: 20rpx;
  312. }
  313. .component-select {
  314. width: 100%;
  315. }
  316. .wtype-section {
  317. margin-bottom: 20rpx;
  318. }
  319. .write-btn {
  320. padding: 2px;
  321. color: #a7a7a7;
  322. margin: 5px;
  323. height: 30px;
  324. }
  325. .action-buttons {
  326. display: flex;
  327. gap: 20rpx;
  328. margin-bottom: 20rpx;
  329. }
  330. .clear-btn {
  331. flex: 1;
  332. }
  333. .device-info {
  334. display: flex;
  335. align-items: center;
  336. gap: 10rpx;
  337. margin-bottom: 10px;
  338. }
  339. .info-label {
  340. font-size: 28rpx;
  341. color: #333;
  342. }
  343. .info-value {
  344. font-size: 28rpx;
  345. color: #666;
  346. }
  347. ::v-deep .input-section .u-button--mini{
  348. width: 100px !important;
  349. height: 30px !important;
  350. }
  351. .typeSelect{
  352. font-size: 16px;
  353. color: #fff;
  354. font-weight: 600;
  355. display: flex;
  356. }
  357. </style>