Sensor.vue 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. <template>
  2. <box
  3. :title="title"
  4. :fullscreen.sync="fullscreen"
  5. :empty="empty"
  6. >
  7. <div
  8. class="l-flex__fill l-flex--col jcenter c-device-dashboard-sensor"
  9. :class="{ fullscreen }"
  10. >
  11. <div
  12. class="l-flex__none c-device-dashboard-sensor__tip u-bold u-text--center"
  13. :style="{ color }"
  14. >
  15. {{ tip }}
  16. </div>
  17. <div class="l-flex__none c-device-dashboard-sensor__current u-text--center">
  18. <template v-if="fullscreen">
  19. {{ sensorTime }} {{ sensorName }}
  20. </template>
  21. <template v-else>
  22. <div>{{ sensorTime }}</div>
  23. <div>{{ sensorName }}</div>
  24. </template>
  25. </div>
  26. <div
  27. v-if="fullscreen && sorted.length > 1"
  28. class="l-flex__fill u-relative"
  29. >
  30. <div class="l-flex__fill c-device-dashboard-sensor__list">
  31. <vue-seamless-scroll
  32. :data="sorted"
  33. :class-option="classOption"
  34. >
  35. <div
  36. v-for="(item,index) in sorted"
  37. :key="index"
  38. class="l-flex--row c-device-dashboard-sensor__item"
  39. >
  40. <div class="l-flex__fill u-text--center u-ellipsis">{{ item.time }}</div>
  41. <div class="l-flex__fill u-text--center u-ellipsis">传感器{{ item.port }}</div>
  42. <div
  43. :style="{ color }"
  44. class="l-flex__fill u-text--center"
  45. >
  46. {{ item.value }}
  47. </div>
  48. </div>
  49. </vue-seamless-scroll>
  50. </div>
  51. </div>
  52. </div>
  53. </box>
  54. </template>
  55. <script>
  56. import { ThirdPartyDevice } from '@/constant'
  57. import { parseTime } from '@/utils'
  58. import { getSensorRecords } from '@/api/external'
  59. import VueSeamlessScroll from 'vue-seamless-scroll'
  60. import Box from './Box'
  61. export default {
  62. components: {
  63. VueSeamlessScroll,
  64. Box
  65. },
  66. props: {
  67. type: {
  68. type: Number,
  69. required: true
  70. },
  71. title: {
  72. type: String,
  73. default: ''
  74. },
  75. color: {
  76. type: String,
  77. default: ''
  78. },
  79. deviceId: {
  80. type: String,
  81. required: true
  82. }
  83. },
  84. data () {
  85. return {
  86. fullscreen: false,
  87. list: [],
  88. classOption: {
  89. step: 0.3,
  90. hoverStop: false
  91. }
  92. }
  93. },
  94. computed: {
  95. sorted () {
  96. return this.list.slice().sort((a, b) => Number(a.value) < Number(b.value) ? 1 : -1)
  97. },
  98. tip () {
  99. return this.sorted.length ? this.sorted[0].info : '未知'
  100. },
  101. sensorTime () {
  102. return this.sorted.length
  103. ? this.sorted[0].time
  104. : null
  105. },
  106. sensorName () {
  107. return this.sorted.length
  108. ? `传感器${this.sorted[0].port}`
  109. : null
  110. },
  111. empty () {
  112. return this.list.length === 0
  113. }
  114. },
  115. created () {
  116. this.$running = true
  117. this.$timer = -1
  118. this.startRun()
  119. },
  120. beforeDestroy () {
  121. this.$running = false
  122. clearTimeout(this.$timer)
  123. },
  124. methods: {
  125. startRun () {
  126. if (!this.$running) {
  127. return
  128. }
  129. const now = Date.now()
  130. this.loading = true
  131. getSensorRecords({
  132. deviceId: this.deviceId,
  133. sensorType: this.type,
  134. startTime: parseTime(now - 30000, '{y}-{m}-{d} {h}:{i}:{s}'),
  135. endTime: parseTime(now, '{y}-{m}-{d} {h}:{i}:{s}')
  136. }, { custom: true }).then(({ data }) => {
  137. this.list = this.transfromData(data)
  138. this.$refs.tableDialog?.getTable()?.pageTo()
  139. }).finally(() => {
  140. this.loading = false
  141. if (this.$running) {
  142. this.$timer = setTimeout(this.startRun, 10000)
  143. }
  144. })
  145. },
  146. transfromData (data) {
  147. const map = {}
  148. const arr = []
  149. data.forEach(sensor => {
  150. if (!map[sensor.port]) {
  151. map[sensor.port] = 1
  152. arr.push(this.transformSensorData(sensor))
  153. }
  154. })
  155. return arr
  156. },
  157. transformSensorData (data) {
  158. const { port, type, value, time } = data
  159. return {
  160. port,
  161. value,
  162. time,
  163. info: this.transformValue(type, value)
  164. }
  165. },
  166. transformValue (type, value) {
  167. switch (type) {
  168. case ThirdPartyDevice.SMOKE_SENSOR:
  169. return `${value}ppm`
  170. case ThirdPartyDevice.TEMPERATURE_SENSOR:
  171. return `${value}℃`
  172. case ThirdPartyDevice.LIGHT_SENSOR:
  173. return `${value}Lux`
  174. case ThirdPartyDevice.FLOODING_SENSOR:
  175. return value ? '是' : '否'
  176. default:
  177. return value
  178. }
  179. },
  180. getSensors () {
  181. return Promise.resolve({ data: this.list })
  182. }
  183. }
  184. }
  185. </script>
  186. <style lang="scss" scoped>
  187. .c-device-dashboard-sensor {
  188. color: #ffffff;
  189. &__tip {
  190. font-size: 24px;
  191. line-height: 36px;
  192. }
  193. &__current {
  194. margin-bottom: 10px;
  195. color: #9ea9cd;
  196. font-size: 12px;
  197. }
  198. &__list {
  199. position: absolute;
  200. top: 0;
  201. left: 0;
  202. width: 100%;
  203. height: 100%;
  204. overflow: hidden;
  205. }
  206. &__item {
  207. font-size: 20px;
  208. line-height: 64px;
  209. border-bottom: 1px solid #9ea9cd;
  210. }
  211. &.fullscreen {
  212. .c-device-dashboard-sensor__tip {
  213. padding-top: 32px;
  214. font-size: 64px;
  215. line-height: 90px;
  216. }
  217. .c-device-dashboard-sensor__current {
  218. margin-bottom: 90px;
  219. font-size: 16px;
  220. }
  221. }
  222. }
  223. </style>