DeviceCardSimple.vue 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. <template>
  2. <div
  3. class="o-device u-pointer"
  4. :data-id="device.id"
  5. @click="onClick"
  6. >
  7. <div class="l-flex__none l-flex--row c-sibling-item--v o-device__block u-font-size u-bold">
  8. <auto-text
  9. class="l-flex__fill c-sibling-item"
  10. :text="name"
  11. />
  12. <template v-if="hasStatus">
  13. <el-tooltip
  14. v-if="isOnline && hasPower"
  15. placement="top"
  16. >
  17. <template #content>{{ powerStatusTip }}</template>
  18. <i
  19. class="l-flex__none c-sibling-item near o-device__status"
  20. :class="switchStatusClass"
  21. @click.stop
  22. />
  23. </el-tooltip>
  24. <el-tooltip placement="top">
  25. <template #content>{{ statusInfoTip }}</template>
  26. <div
  27. class="l-flex__none o-device__tip u-font-size--xs"
  28. :class="statusClass"
  29. >
  30. <span class="u-color--white">{{ statusTip }}</span>
  31. </div>
  32. </el-tooltip>
  33. </template>
  34. <i
  35. v-else
  36. class="l-flex__none c-sibling-item near el-icon-loading"
  37. />
  38. </div>
  39. <div class="l-flex__none l-flex--row c-sibling-item--v nearer o-device__block u-relative u-color--blue">
  40. <i class="l-flex__none c-sibling-item el-icon-location-outline u-font-size" />
  41. <auto-text
  42. class="l-flex__auto c-sibling-item nearest u-font-size--xs u-bold"
  43. :text="address"
  44. />
  45. <div
  46. v-if="isOnline && volume > -1"
  47. class="l-flex__none o-device__volume u-color--white u-font-size--sm has-active"
  48. @click.stop="onVolume"
  49. >
  50. <template v-if="volume === 0">
  51. <svg-icon icon-class="mute" />
  52. </template>
  53. <template v-else>
  54. <svg-icon
  55. class="c-sibling-item"
  56. icon-class="volume"
  57. />
  58. <span class="c-sibling-item nearest">{{ volumeTip }}</span>
  59. </template>
  60. </div>
  61. </div>
  62. </div>
  63. </template>
  64. <script>
  65. import { ThirdPartyDevice } from '@/constant'
  66. import { parseTime } from '@/utils'
  67. import {
  68. Status,
  69. Power,
  70. addListener,
  71. removeListener
  72. } from '@/utils/adapter'
  73. import { parseVolume } from '@/utils/control/volume'
  74. export default {
  75. name: 'DeviceCardSimple',
  76. props: {
  77. device: {
  78. type: Object,
  79. required: true
  80. }
  81. },
  82. data () {
  83. return {
  84. timestamp: '',
  85. powerStatus: Status.LOADING,
  86. switchStatus: Power.LOADING,
  87. hasPower: true,
  88. hasPowerRealStatus: false,
  89. volume: -1
  90. }
  91. },
  92. computed: {
  93. name () {
  94. return this.device.name
  95. },
  96. address () {
  97. return this.device.address
  98. },
  99. powerStatusTip () {
  100. return this.hasPower
  101. ? this.powerStatus === Status.WARNING
  102. ? `电源状态异常,${this.switchStatus === Power.LOADING ? '检测' : '最后上报'}时间 ${this.timestamp}`
  103. : this.isPowerOpened
  104. ? '屏幕已开启'
  105. : '屏幕未开启'
  106. : ''
  107. },
  108. isOnline () {
  109. return this.device.onlineStatus === 1
  110. },
  111. hasStatus () {
  112. return !this.isOnline || !this.hasPower || this.hasPowerRealStatus
  113. },
  114. isPowerOpened () {
  115. return !this.hasPower || this.hasPowerRealStatus && (this.powerStatus === Status.OK && this.switchStatus !== Power.OFF)
  116. },
  117. isRealOnline () {
  118. return this.hasStatus && this.isOnline && this.isPowerOpened
  119. },
  120. isRealOffline () {
  121. return this.hasStatus && !this.isRealOnline
  122. },
  123. switchStatusClass () {
  124. if (this.powerStatus === Status.WARNING) {
  125. return 'el-icon-warning u-color--warning u-font-size--2xl'
  126. }
  127. return this.switchStatus === Power.ON ? 'on' : this.switchStatus === Power.OFF ? 'off' : 'other'
  128. },
  129. statusClass () {
  130. return this.isOnline ? 'u-color--success dark' : 'u-color--error dark'
  131. },
  132. statusTip () {
  133. return this.isOnline ? '在线' : '离线'
  134. },
  135. statusInfoTip () {
  136. return this.device.lastOnline
  137. ? this.isOnline
  138. ? `${this.device.lastOnline} 上线`
  139. : `${this.device.lastOnline} 离线`
  140. : this.isOnline
  141. ? '播控器正常运行中'
  142. : '当前播控器离线了'
  143. },
  144. volumeTip () {
  145. if (this.volume > -1) {
  146. return parseVolume(this.volume)
  147. }
  148. return ''
  149. }
  150. },
  151. watch: {
  152. isOnline: {
  153. handler (val, old) {
  154. if (val) {
  155. addListener(this.device.id, this.onMessage)
  156. } else {
  157. if (old == null) {
  158. return
  159. }
  160. removeListener(this.device.id, this.onMessage)
  161. }
  162. },
  163. immediate: true
  164. }
  165. },
  166. beforeDestroy () {
  167. if (this.isOnline) {
  168. removeListener(this.device.id, this.onMessage)
  169. }
  170. },
  171. methods: {
  172. onMessage (value) {
  173. if (value.screen) {
  174. this.volume = value.screen.volume
  175. }
  176. const multiCard = value[ThirdPartyDevice.MULTI_FUNCTION_CARD]
  177. const powerStatus = multiCard.status
  178. this.powerStatus = powerStatus
  179. this.timestamp = multiCard.timestamp ? parseTime(multiCard.timestamp, '{y}-{m}-{d} {h}:{i}:{s}') : ''
  180. this.hasPower = powerStatus > Status.NONE
  181. this.hasPowerRealStatus = powerStatus !== Status.LOADING
  182. this.switchStatus = multiCard.switchStatus
  183. },
  184. onClick () {
  185. this.$router.push({
  186. name: 'device-detail',
  187. params: { id: this.device.id }
  188. })
  189. },
  190. onVolume () {
  191. const { id, productId, name } = this.device
  192. this.$emit('volume', {
  193. value: this.volume,
  194. device: { id, productId, name }
  195. })
  196. }
  197. }
  198. }
  199. </script>
  200. <style lang="scss" scoped>
  201. .o-device {
  202. display: inline-flex;
  203. flex-direction: column;
  204. padding: $padding--2xs $padding--xs;
  205. color: $black;
  206. line-height: 1;
  207. border-radius: $radius;
  208. background-color: #fff;
  209. box-shadow: 0 4px 12px 0 rgba(0, 0, 0, 0.1), 0 2px 6px 0 rgba(0, 0, 0, 0.1);
  210. &__block {
  211. height: 24px;
  212. }
  213. &__status {
  214. display: inline-flex;
  215. justify-content: center;
  216. align-items: center;
  217. width: 24px;
  218. height: 24px;
  219. &.on {
  220. background: url("~@/assets/icon_on.svg") 0 0 / 100% 100% no-repeat;
  221. }
  222. &.off {
  223. background: url("~@/assets/icon_off.svg") 0 0 / 100% 100% no-repeat;
  224. }
  225. &.other {
  226. width: 54px;
  227. background: url("~@/assets/icon_on_2.svg") 0 0 / 100% 100% no-repeat;
  228. }
  229. }
  230. &__tip {
  231. display: inline-block;
  232. position: relative;
  233. left: $padding--xs;
  234. padding: $padding--2xs $padding--sm $padding--2xs $padding;
  235. border-radius: $radius--sm 0 0 $radius--sm;
  236. background-color: currentColor;
  237. }
  238. &__volume {
  239. display: inline-block;
  240. position: relative;
  241. left: $padding--xs;
  242. padding: $padding--2xs;
  243. border-radius: $radius--sm 0 0 $radius--sm;
  244. background-color: $gray--dark;
  245. }
  246. }
  247. </style>