Ver código fonte

feat(dashboard): adjust rect card style

Casper Dai 2 anos atrás
pai
commit
533f3c6609

+ 10 - 1
src/scss/bem/_layout.scss

@@ -80,9 +80,9 @@
   display: grid;
   grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
   grid-template-rows: max-content;
+  align-items: start;
   row-gap: $spacing;
   column-gap: $spacing;
-  align-items: start;
   min-height: 0;
   min-width: 0;
 
@@ -98,3 +98,12 @@
     grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
   }
 }
+
+.l-grid--rect {
+  display: grid;
+  grid-template-columns: repeat(auto-fill, 36px);
+  grid-template-rows: repeat(auto-fill, 36px);
+  align-items: start;
+  gap: 2px;
+  min-height: 0;
+}

+ 3 - 3
src/views/dashboard/components/DeviceCardRect.vue

@@ -198,8 +198,8 @@ export default {
   display: inline-flex;
   justify-content: center;
   align-items: center;
-  width: 48px;
-  height: 48px;
+  width: 36px;
+  height: 36px;
   vertical-align: top;
   background-color: currentColor;
 
@@ -219,7 +219,7 @@ export default {
     }
 
     &.other {
-      width: 40px;
+      width: 32px;
       background: url("~@/assets/icon_on_2.svg") 0 0 / 100% 100% no-repeat;
     }
   }

+ 1 - 10
src/views/dashboard/components/DeviceGroupAttention.vue

@@ -1,8 +1,5 @@
 <template>
-  <div
-    class="c-device-group-attention"
-    :class="{ 'l-grid--info': hasData }"
-  >
+  <div :class="gridClass">
     <template v-if="hasData">
       <component
         :is="cardComponent"
@@ -87,9 +84,3 @@ export default {
   }
 }
 </script>
-
-<style lang="scss" scoped>
-.c-device-group-attention {
-  min-height: 360px;
-}
-</style>

+ 4 - 1
src/views/dashboard/components/DeviceGroupLevelItem.vue

@@ -1,7 +1,10 @@
 <template>
   <div v-if="hasData">
     <div class="c-sibling-item--v u-color--black u-font-size--sm u-bold">{{ group.name }}</div>
-    <div class="c-sibling-item--v near l-grid--info">
+    <div
+      class="c-sibling-item--v near"
+      :class="gridClass"
+    >
       <component
         :is="cardComponent"
         v-for="device in filterList"

+ 0 - 134
src/views/dashboard/components/DeviceGroupRect.vue

@@ -1,134 +0,0 @@
-<template>
-  <div class="c-device-group-rect u-overflow-y--auto">
-    <div
-      v-if="hasData"
-      class="c-device-group-rect__content"
-    >
-      <device-card-rect
-        v-for="item in groupOptions.list"
-        :key="item.id"
-        :device="item"
-        @volume="onVolume"
-      />
-      <volume-dialog ref="volumeDialog" />
-    </div>
-    <div
-      v-else-if="groupOptions.loading"
-      class="has-padding--v u-text--center"
-    >
-      <i class="el-icon-loading u-font-size--lg" />
-    </div>
-    <el-empty v-else />
-  </div>
-</template>
-
-<script>
-import { getDevicesByQuery } from '@/api/device'
-import groupMixin from './mixins/group.js'
-import DeviceCardRect from './DeviceCardRect.vue'
-import VolumeDialog from './VolumeDialog.vue'
-
-export default {
-  name: 'DeviceGroupRect',
-  components: {
-    DeviceCardRect,
-    VolumeDialog
-  },
-  mixins: [groupMixin],
-  props: {
-    path: {
-      type: String,
-      required: true
-    },
-    total: {
-      type: Number,
-      default: -1
-    }
-  },
-  computed: {
-    hasData () {
-      return this.groupOptions.list.some(({ onlineStatus }) => onlineStatus === 1)
-    }
-  },
-  watch: {
-    path () {
-      this.refreshGroups(true)
-    },
-    total () {
-      this.refreshGroups(true)
-    }
-  },
-  methods: {
-    refreshGroups (force) {
-      if (!this.path || !force && this.groupOptions.loading) {
-        return
-      }
-      this.onResetGroupOptions()
-
-      const groupOptions = this.createGroupOptions(
-        this.total === 0
-          ? { loaded: true }
-          : { loading: true }
-      )
-      this.groupOptions = groupOptions
-      this.onChanged()
-      if (this.total <= 0) {
-        return
-      }
-
-      getDevicesByQuery({
-        pageNum: 1,
-        pageSize: this.total,
-        activate: 1,
-        org: this.path
-      }, { custom: true }).then(
-        ({ data }) => {
-          if (groupOptions.ignore) {
-            return
-          }
-          const map = {}
-          const topics = []
-          groupOptions.list = data.map(device => {
-            const item = this.transformDevice(device)
-            map[device.id] = item
-            topics.push(...this.createTopics(item))
-            return item
-          })
-          groupOptions.map = map
-          groupOptions.loaded = true
-          this.onChanged()
-          this.onSubscribe(topics)
-        },
-        ({ isCancel }) => {
-          if (isCancel || groupOptions.ignore) {
-            return
-          }
-          this.$timer = setTimeout(this.refreshGroups, 2000)
-        }
-      ).finally(() => {
-        groupOptions.loading = false
-      })
-    },
-    onChanged () {
-      this.$emit('change', [{
-        children: [...this.groupOptions.list]
-      }])
-    },
-    onVolume ({ value, device }) {
-      this.$refs.volumeDialog.show(value, device)
-    }
-  }
-}
-</script>
-
-<style lang="scss" scoped>
-.c-device-group-rect {
-  min-height: 64px;
-
-  &__content {
-    display: flex;
-    flex-wrap: wrap;
-    gap: 2px;
-  }
-}
-</style>

+ 1 - 10
src/views/dashboard/components/DeviceGroupTile.vue

@@ -1,8 +1,5 @@
 <template>
-  <div
-    class="c-device-group-tile"
-    :class="{ 'l-grid--info': hasData }"
-  >
+  <div :class="gridClass">
     <template v-if="hasData">
       <component
         :is="cardComponent"
@@ -114,9 +111,3 @@ export default {
   }
 }
 </script>
-
-<style lang="scss" scoped>
-.c-device-group-tile {
-  min-height: 360px;
-}
-</style>

+ 48 - 43
src/views/dashboard/components/DeviceGroups.vue

@@ -26,12 +26,6 @@
           >
             层级
           </el-dropdown-item>
-          <el-dropdown-item
-            icon="el-icon-menu"
-            command="rect"
-          >
-            方块图
-          </el-dropdown-item>
           <el-dropdown-item
             v-if="isTenantAdmin"
             icon="el-icon-star-off"
@@ -53,13 +47,27 @@
       </div>
       <slot />
       <div class="l-flex__fill" />
-      <div
-        v-if="supportCardStyle"
-        class="l-flex__none l-flex--row u-color--blue u-font-size--sm has-active"
-        @click="onSwitchCardStyle"
+      <el-dropdown
+        class="l-flex__none c-sibling-item"
+        trigger="click"
+        @command="onSwitchCardStyle"
       >
-        {{ tip }}
-      </div>
+        <div class="l-flex--row inline u-font-size--sm has-active">
+          <span class="c-sibling-item ">{{ cardStyleTip }}</span>
+          <i class="c-sibling-item nearer el-icon-arrow-down" />
+        </div>
+        <el-dropdown-menu slot="dropdown">
+          <el-dropdown-item command="big">
+            详情
+          </el-dropdown-item>
+          <el-dropdown-item command="medium">
+            简略
+          </el-dropdown-item>
+          <el-dropdown-item command="rect">
+            方块
+          </el-dropdown-item>
+        </el-dropdown-menu>
+      </el-dropdown>
     </div>
     <component
       :is="activeComponent"
@@ -76,26 +84,34 @@
 import { mapGetters } from 'vuex'
 import DeviceGroupTile from './DeviceGroupTile.vue'
 import DeviceGroupLevel from './DeviceGroupLevel.vue'
-import DeviceGroupRect from './DeviceGroupRect.vue'
 import DeviceGroupAttention from './DeviceGroupAttention.vue'
 import VolumeDrawer from './DrawerVolumeSettings.vue'
 
-const groupStyleCommands = ['tile', 'level', 'rect']
-const cardStyleCommands = ['big', 'medium']
+const groupStyleCommands = new Set(['tile', 'level'])
+const defaultGroupStyle = 'tile'
+const cardStyleCommands = new Set(['big', 'medium', 'rect'])
+const defaultcardStyle = 'big'
 
 export default {
   name: 'DeviceGroups',
   components: {
     DeviceGroupTile,
     DeviceGroupLevel,
-    DeviceGroupRect,
     DeviceGroupAttention,
     VolumeDrawer
   },
   data () {
+    if (this.$store.getters.isTenantAdmin) {
+      if (!groupStyleCommands.has('attention')) {
+        groupStyleCommands.add('attention')
+      }
+    } else if (groupStyleCommands.has('attention')) {
+      groupStyleCommands.delete('attention')
+    }
+
     let options = {
-      groupStyle: groupStyleCommands[0],
-      cardStyle: cardStyleCommands[0]
+      groupStyle: defaultGroupStyle,
+      cardStyle: defaultcardStyle
     }
     try {
       options = {
@@ -107,8 +123,8 @@ export default {
     }
 
     return {
-      groupStyle: groupStyleCommands.includes(options.groupStyle) ? options.groupStyle : groupStyleCommands[0],
-      cardStyle: cardStyleCommands.includes(options.cardStyle) ? options.cardStyle : cardStyleCommands[0],
+      groupStyle: groupStyleCommands.has(options.groupStyle) ? options.groupStyle : defaultGroupStyle,
+      cardStyle: cardStyleCommands.has(options.cardStyle) ? options.cardStyle : defaultcardStyle,
       groups: []
     }
   },
@@ -118,8 +134,6 @@ export default {
       switch (this.groupStyle) {
         case 'attention':
           return '我的关注'
-        case 'rect':
-          return '方块图'
         default:
           return '设备列表'
       }
@@ -128,8 +142,6 @@ export default {
       switch (this.groupStyle) {
         case 'tile':
           return 'el-icon-s-grid'
-        case 'rect':
-          return 'el-icon-menu'
         case 'attention':
           return 'el-icon-star-off'
         default:
@@ -140,36 +152,30 @@ export default {
       switch (this.groupStyle) {
         case 'tile':
           return 'DeviceGroupTile'
-        case 'rect':
-          return 'DeviceGroupRect'
         case 'attention':
           return 'DeviceGroupAttention'
         default:
           return 'DeviceGroupLevel'
       }
     },
-    hasData () {
-      return this.groups.some(({ children }) => children.some(({ onlineStatus }) => onlineStatus === 1))
-    },
-    supportCardStyle () {
-      switch (this.groupStyle) {
+    cardStyleTip () {
+      switch (this.cardStyle) {
+        case 'medium':
+          return '简略'
         case 'rect':
-          return false
+          return '方块'
         default:
-          return true
+          return '详情'
       }
     },
-    tip () {
-      if (this.cardStyle === 'big') {
-        return '切换至简洁模式'
-      }
-      return '切换至详情模式'
+    hasData () {
+      return this.groups.some(({ children }) => children.some(({ onlineStatus }) => onlineStatus === 1))
     }
   },
   methods: {
     onCommand (groupStyle) {
       this.groupStyle = groupStyle
-      this.saveOptions(groupStyleCommands.includes(groupStyle) ? groupStyle : '', this.cardStyle)
+      this.saveOptions(groupStyleCommands.has(groupStyle) ? groupStyle : '', this.cardStyle)
     },
     onVolume () {
       this.$refs.drawer.show(this.groups)
@@ -177,10 +183,9 @@ export default {
     onChange (groups) {
       this.groups = groups
     },
-    onSwitchCardStyle () {
-      const next = this.cardStyle === 'big' ? 'medium' : 'big'
-      this.cardStyle = next
-      this.saveOptions(this.groupStyle, cardStyleCommands.includes(next) ? next : '')
+    onSwitchCardStyle (cardStyle) {
+      this.cardStyle = cardStyle
+      this.saveOptions(this.groupStyle, cardStyleCommands.has(cardStyle) ? cardStyle : '')
     },
     saveOptions (groupStyle, cardStyle) {
       localStorage.setItem(`MSR_DASHBOARD__STYLE__${this.account}`, JSON.stringify({ groupStyle, cardStyle }))

+ 26 - 0
src/views/dashboard/components/mixins/group-list.js

@@ -1,5 +1,6 @@
 import DeviceCard from '../DeviceCard.vue'
 import DeviceCardSimple from '../DeviceCardSimple.vue'
+import DeviceCardRect from '../DeviceCardRect.vue'
 import VolumeDialog from '../VolumeDialog.vue'
 
 export default {
@@ -16,6 +17,7 @@ export default {
   components: {
     DeviceCard,
     DeviceCardSimple,
+    DeviceCardRect,
     VolumeDialog
   },
   computed: {
@@ -23,10 +25,31 @@ export default {
       switch (this.cardStyle) {
         case 'medium':
           return 'DeviceCardSimple'
+        case 'rect':
+          return 'DeviceCardRect'
         default:
           return 'DeviceCard'
       }
     },
+    needFilterAndSort () {
+      switch (this.cardStyle) {
+        case 'rect':
+          return false
+        default:
+          return true
+      }
+    },
+    gridClass () {
+      if (this.hasData) {
+        switch (this.cardStyle) {
+          case 'rect':
+            return 'l-grid--rect'
+          default:
+            return 'l-grid--info'
+        }
+      }
+      return ''
+    },
     groupItems () {
       return []
     },
@@ -34,6 +57,9 @@ export default {
       return [...this.groupItems].sort(this.sort)
     },
     filterList () {
+      if (!this.needFilterAndSort) {
+        return [...this.groupItems]
+      }
       if (!this.status) {
         return this.list
       }

+ 0 - 4
src/views/dashboard/components/mixins/group.js

@@ -74,12 +74,8 @@ export default {
             if (topicKey !== (device.onlineStatus === 1 ? 'online' : 'offline')) {
               if (topicKey === 'online') {
                 device.onlineStatus = 1
-                this.groupOptions.online += 1
-                this.groupOptions.offline -= 1
               } else {
                 device.onlineStatus = 2
-                this.groupOptions.online -= 1
-                this.groupOptions.offline += 1
               }
               device.lastOnline = parseTime(new Date(), '{y}-{m}-{d} {h}:{i}:{s}')
               this.onStatusChanged(topicKey)