|
|
@@ -0,0 +1,234 @@
|
|
|
+<template>
|
|
|
+ <el-popover
|
|
|
+ placement="top"
|
|
|
+ width="320"
|
|
|
+ trigger="click"
|
|
|
+ >
|
|
|
+ <div>
|
|
|
+ <div
|
|
|
+ class="l-flex--row c-sibling-item--v u-bold has-active"
|
|
|
+ @click="onClick"
|
|
|
+ >
|
|
|
+ <div class="l-flex__fill c-sibling-item">{{ name }}</div>
|
|
|
+ <i class="c-sibling-item--v el-icon-arrow-right" />
|
|
|
+ </div>
|
|
|
+ <div class="l-flex--row c-sibling-item--v near u-color--blue">
|
|
|
+ <i class="l-flex__none c-sibling-item el-icon-location-outline u-font-size" />
|
|
|
+ <auto-text
|
|
|
+ class="l-flex__auto c-sibling-item nearest u-font-size--xs u-bold"
|
|
|
+ :text="address"
|
|
|
+ />
|
|
|
+ <div
|
|
|
+ v-if="isOnline && volume > -1"
|
|
|
+ class="l-flex__none o-device__volume u-color--white u-font-size--sm has-active"
|
|
|
+ @click.stop="onVolume"
|
|
|
+ >
|
|
|
+ <template v-if="volume === 0">
|
|
|
+ <svg-icon icon-class="mute" />
|
|
|
+ </template>
|
|
|
+ <template v-else>
|
|
|
+ <svg-icon
|
|
|
+ class="c-sibling-item"
|
|
|
+ icon-class="volume"
|
|
|
+ />
|
|
|
+ <span class="c-sibling-item nearest">{{ volumeTip }}</span>
|
|
|
+ </template>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div
|
|
|
+ v-if="statusTip"
|
|
|
+ class="c-sibling-item--v"
|
|
|
+ >
|
|
|
+ {{ statusTip }}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <template #reference>
|
|
|
+ <div
|
|
|
+ class="o-device u-pointer"
|
|
|
+ :class="statusClass"
|
|
|
+ >
|
|
|
+ <i
|
|
|
+ v-if="!hasStatus"
|
|
|
+ class="el-icon-loading u-color--white"
|
|
|
+ />
|
|
|
+ <i
|
|
|
+ v-if="isOnline && hasStatus"
|
|
|
+ class="o-device__status"
|
|
|
+ :class="switchStatusClass"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </el-popover>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+import { ThirdPartyDevice } from '@/constant'
|
|
|
+import { parseTime } from '@/utils'
|
|
|
+import {
|
|
|
+ Status,
|
|
|
+ Power,
|
|
|
+ addListener,
|
|
|
+ removeListener
|
|
|
+} from '@/utils/adapter'
|
|
|
+import { parseVolume } from '@/utils/control/volume'
|
|
|
+
|
|
|
+export default {
|
|
|
+ name: 'DeviceCardRect',
|
|
|
+ props: {
|
|
|
+ device: {
|
|
|
+ type: Object,
|
|
|
+ required: true
|
|
|
+ }
|
|
|
+ },
|
|
|
+ data () {
|
|
|
+ return {
|
|
|
+ powerStatus: Status.LOADING,
|
|
|
+ switchStatus: Power.LOADING,
|
|
|
+ hasPower: true,
|
|
|
+ hasPowerRealStatus: false,
|
|
|
+ volume: -1
|
|
|
+ }
|
|
|
+ },
|
|
|
+ computed: {
|
|
|
+ name () {
|
|
|
+ return this.device.name
|
|
|
+ },
|
|
|
+ address () {
|
|
|
+ return this.device.address
|
|
|
+ },
|
|
|
+ isOnline () {
|
|
|
+ return this.device.onlineStatus === 1
|
|
|
+ },
|
|
|
+ hasStatus () {
|
|
|
+ return !this.isOnline || !this.hasPower || this.hasPowerRealStatus
|
|
|
+ },
|
|
|
+ isPowerOpened () {
|
|
|
+ return !this.hasPower || this.hasPowerRealStatus && (this.powerStatus === Status.OK && this.switchStatus !== Power.OFF)
|
|
|
+ },
|
|
|
+ switchStatusClass () {
|
|
|
+ if (this.powerStatus === Status.WARNING) {
|
|
|
+ return ''
|
|
|
+ }
|
|
|
+ return this.switchStatus === Power.ON ? 'on' : this.switchStatus === Power.OFF ? 'off' : 'other'
|
|
|
+ },
|
|
|
+ statusClass () {
|
|
|
+ if (this.hasStatus) {
|
|
|
+ return this.isOnline
|
|
|
+ ? this.hasPower
|
|
|
+ ? this.powerStatus === Status.WARNING
|
|
|
+ ? 'u-color--warning'
|
|
|
+ : 'u-color--success dark'
|
|
|
+ : 'u-color--success dark'
|
|
|
+ : 'u-color--error dark'
|
|
|
+ }
|
|
|
+ return 'u-color--info light'
|
|
|
+ },
|
|
|
+ statusTip () {
|
|
|
+ return this.hasPowerRealStatus
|
|
|
+ ? this.powerStatus === Status.WARNING
|
|
|
+ ? `电源状态异常,${this.switchStatus === Power.LOADING ? '检测' : '最后上报'}时间 ${this.timestamp}`
|
|
|
+ : this.isPowerOpened
|
|
|
+ ? '屏幕已开启'
|
|
|
+ : '屏幕未开启'
|
|
|
+ : this.device.lastOnline
|
|
|
+ ? this.isOnline
|
|
|
+ ? `${this.device.lastOnline} 上线`
|
|
|
+ : `${this.device.lastOnline} 离线`
|
|
|
+ : ''
|
|
|
+ },
|
|
|
+ volumeTip () {
|
|
|
+ if (this.volume > -1) {
|
|
|
+ return parseVolume(this.volume)
|
|
|
+ }
|
|
|
+ return ''
|
|
|
+ }
|
|
|
+ },
|
|
|
+ watch: {
|
|
|
+ isOnline: {
|
|
|
+ handler (val, old) {
|
|
|
+ if (val) {
|
|
|
+ addListener(this.device.id, this.onMessage)
|
|
|
+ } else {
|
|
|
+ if (old == null) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ removeListener(this.device.id, this.onMessage)
|
|
|
+ }
|
|
|
+ },
|
|
|
+ immediate: true
|
|
|
+ }
|
|
|
+ },
|
|
|
+ beforeDestroy () {
|
|
|
+ if (this.isOnline) {
|
|
|
+ removeListener(this.device.id, this.onMessage)
|
|
|
+ }
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ onMessage (value) {
|
|
|
+ if (value.screen) {
|
|
|
+ this.volume = value.screen.volume
|
|
|
+ }
|
|
|
+ const multiCard = value[ThirdPartyDevice.MULTI_FUNCTION_CARD]
|
|
|
+ const powerStatus = multiCard.status
|
|
|
+ this.powerStatus = powerStatus
|
|
|
+ this.timestamp = multiCard.timestamp ? parseTime(multiCard.timestamp, '{y}-{m}-{d} {h}:{i}:{s}') : ''
|
|
|
+ this.hasPower = powerStatus > Status.NONE
|
|
|
+ this.hasPowerRealStatus = powerStatus !== Status.LOADING
|
|
|
+ this.switchStatus = multiCard.switchStatus
|
|
|
+ },
|
|
|
+ onClick () {
|
|
|
+ this.$router.push({
|
|
|
+ name: 'device-detail',
|
|
|
+ params: { id: this.device.id }
|
|
|
+ })
|
|
|
+ },
|
|
|
+ onVolume () {
|
|
|
+ const { id, productId, name } = this.device
|
|
|
+ this.$emit('volume', {
|
|
|
+ value: this.volume,
|
|
|
+ device: { id, productId, name }
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+.o-device {
|
|
|
+ display: inline-flex;
|
|
|
+ justify-content: center;
|
|
|
+ align-items: center;
|
|
|
+ width: 48px;
|
|
|
+ height: 48px;
|
|
|
+ vertical-align: top;
|
|
|
+ background-color: currentColor;
|
|
|
+
|
|
|
+ &__status {
|
|
|
+ display: inline-flex;
|
|
|
+ justify-content: center;
|
|
|
+ align-items: center;
|
|
|
+ width: 24px;
|
|
|
+ height: 24px;
|
|
|
+
|
|
|
+ &.on {
|
|
|
+ background: url("~@/assets/icon_on.svg") 0 0 / 100% 100% no-repeat;
|
|
|
+ }
|
|
|
+
|
|
|
+ &.off {
|
|
|
+ background: url("~@/assets/icon_off.svg") 0 0 / 100% 100% no-repeat;
|
|
|
+ }
|
|
|
+
|
|
|
+ &.other {
|
|
|
+ width: 40px;
|
|
|
+ background: url("~@/assets/icon_on_2.svg") 0 0 / 100% 100% no-repeat;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ &__volume {
|
|
|
+ display: inline-block;
|
|
|
+ padding: $padding--2xs;
|
|
|
+ border-radius: $radius--sm;
|
|
|
+ background-color: $gray--dark;
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|