index.vue 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. <template>
  2. <div class="app-container tsb-home">
  3. <div class="tsb-home-header">
  4. <h2 class="tsb-home-title">调试宝设备</h2>
  5. </div>
  6. <div v-loading="loading">
  7. <div v-if="onlineDevices.length" class="section-block">
  8. <div class="section-title">
  9. <span>已登录设备</span>
  10. <el-tag size="mini" type="success">{{ onlineDevices.length }}</el-tag>
  11. </div>
  12. <el-row :gutter="16">
  13. <el-col v-for="item in onlineDevices" :key="'on-' + item.deviceId" :xs="24" :sm="12" :md="8" :lg="6">
  14. <device-card :device="item" :active="isActive(item)" @operate="handleOperate" />
  15. </el-col>
  16. </el-row>
  17. </div>
  18. <el-collapse v-if="offlineDevices.length" v-model="offlineCollapse" class="offline-collapse">
  19. <el-collapse-item name="offline">
  20. <template slot="title">
  21. <span class="section-title inline">
  22. <span>未登录设备</span>
  23. <el-tag size="mini" type="info">{{ offlineDevices.length }}</el-tag>
  24. <span class="collapse-hint">点击标题可展开/收起</span>
  25. </span>
  26. </template>
  27. <el-row :gutter="16">
  28. <el-col v-for="item in offlineDevices" :key="'off-' + item.deviceId" :xs="24" :sm="12" :md="8" :lg="6">
  29. <device-card :device="item" offline />
  30. </el-col>
  31. </el-row>
  32. </el-collapse-item>
  33. </el-collapse>
  34. <el-empty v-if="!loading && !deviceList.length" description="暂无调试宝设备" />
  35. </div>
  36. </div>
  37. </template>
  38. <script>
  39. import { listTsbDeviceHome } from '@/api/tsb/device'
  40. import tsbWebSocket from '@/utils/tsbWebSocket'
  41. import { navigateToWorkspace } from '@/utils/tsbWorkspaceNav'
  42. import DeviceCard from './dashboard/DeviceCard'
  43. export default {
  44. name: 'Index',
  45. components: { DeviceCard },
  46. data() {
  47. return {
  48. loading: false,
  49. deviceList: [],
  50. offlineCollapse: [],
  51. refreshTimer: null,
  52. connectingDeviceSn: null
  53. }
  54. },
  55. computed: {
  56. onlineDevices() {
  57. return this.deviceList.filter(d => Number(d.lineStatus) === 1)
  58. },
  59. offlineDevices() {
  60. return this.deviceList.filter(d => Number(d.lineStatus) !== 1)
  61. },
  62. openedDevices() {
  63. return this.$store.getters.tsbOpenedDevices || []
  64. }
  65. },
  66. created() {
  67. this.loadDevices()
  68. this.refreshTimer = setInterval(() => this.loadDevices(true), 30000)
  69. },
  70. beforeDestroy() {
  71. if (this.refreshTimer) {
  72. clearInterval(this.refreshTimer)
  73. }
  74. },
  75. methods: {
  76. loadDevices(silent) {
  77. if (!silent) {
  78. this.loading = true
  79. }
  80. listTsbDeviceHome().then(res => {
  81. const data = res.data
  82. this.deviceList = Array.isArray(data) ? data : []
  83. }).catch(() => {
  84. this.deviceList = []
  85. }).finally(() => {
  86. this.loading = false
  87. })
  88. },
  89. isActive(device) {
  90. return this.openedDevices.some(d => d.deviceSn === device.deviceSn)
  91. },
  92. handleOperate(device) {
  93. if (this.connectingDeviceSn === device.deviceSn) {
  94. return
  95. }
  96. this.connectingDeviceSn = device.deviceSn
  97. tsbWebSocket.connectWithDevice(device).then(() => {
  98. navigateToWorkspace().catch(() => {})
  99. }).catch((err) => {
  100. const msg = typeof err === 'string' ? err : (err && (err.message || err.msg)) || '设备连接失败'
  101. this.$message.error(msg)
  102. }).finally(() => {
  103. this.connectingDeviceSn = null
  104. })
  105. }
  106. }
  107. }
  108. </script>
  109. <style scoped lang="scss">
  110. .tsb-home-header {
  111. margin-bottom: 16px;
  112. }
  113. .tsb-home-title {
  114. margin: 0;
  115. font-size: 20px;
  116. font-weight: 600;
  117. }
  118. .section-block {
  119. margin-bottom: 20px;
  120. }
  121. .section-title {
  122. display: flex;
  123. align-items: center;
  124. gap: 8px;
  125. margin-bottom: 12px;
  126. font-size: 15px;
  127. font-weight: 500;
  128. &.inline {
  129. margin-bottom: 0;
  130. }
  131. }
  132. .collapse-hint {
  133. margin-left: 4px;
  134. font-size: 12px;
  135. font-weight: normal;
  136. color: #909399;
  137. }
  138. .offline-collapse {
  139. border: none;
  140. ::v-deep .el-collapse-item__header {
  141. border-bottom: none;
  142. font-size: 15px;
  143. }
  144. ::v-deep .el-collapse-item__wrap {
  145. border-bottom: none;
  146. }
  147. }
  148. </style>