Explorar el Código

feat: device grouping

Casper Dai hace 3 años
padre
commit
fde3fafb4e

+ 5 - 0
src/api/base.js

@@ -62,6 +62,11 @@ export function addOrg (data) {
   return data
 }
 
+export function addUser (data) {
+  data.user = store.getters.userId
+  return data
+}
+
 export function canDel ({ createBy, org }) {
   if (store.getters.isSuperAdmin) {
     return true

+ 12 - 22
src/api/device.js

@@ -8,7 +8,8 @@ import {
   send,
   confirmAndSend,
   addTenant,
-  addScope
+  addScope,
+  addUser
 } from './base'
 import { toEvent } from '@/utils/event'
 
@@ -96,19 +97,6 @@ export function deleteDevice ({ id, name }) {
   })
 }
 
-// export function getDevices (query, options) {
-//   const { pageNum: pageIndex, pageSize, ...params } = query
-//   return request({
-//     url: '/device/list',
-//     method: 'GET',
-//     params: addGroup({
-//       pageIndex, pageSize,
-//       ...params
-//     }),
-//     ...options
-//   })
-// }
-
 export function getDevices (query, options) {
   const { pageNum: pageIndex, pageSize, ...params } = query
   return tenantRequest({
@@ -302,7 +290,7 @@ export function addDeviceGroup (data) {
 export function updateDeviceGroup (data) {
   return update({
     url: '/deviceGroup',
-    method: 'put',
+    method: 'PUT',
     data
   })
 }
@@ -316,27 +304,29 @@ export function deleteDeviceGroup ({ id, name }) {
 
 export function getDeviceGroups (query) {
   const { pageNum: pageIndex, pageSize, ...params } = query
-  return request({
+  return tenantRequest({
     url: '/deviceGroup/list',
     method: 'GET',
-    params: {
+    params: addUser({
       pageIndex, pageSize,
       ...params
-    }
+    })
   })
 }
 
 export function getDevicesByGroup (id) {
-  return request({
+  return tenantRequest({
     url: `/deviceGroup/${id}/device`,
-    method: 'GET'
+    method: 'GET',
+    params: addScope({})
   })
 }
 
 export function getDeviceTree () {
-  return request({
+  return tenantRequest({
     url: '/deviceGroup/deviceTree',
-    method: 'GET'
+    method: 'GET',
+    params: addUser(addScope({}))
   })
 }
 

+ 0 - 0
src/components/StatusWrapper/index.vue → src/components/layout/StatusWrapper/index.vue


+ 0 - 0
src/components/Wrapper/index.vue → src/components/layout/Wrapper/index.vue


+ 85 - 155
src/components/DeviceTree/back.vue → src/components/tree/DeviceGroupTree/index.vue

@@ -7,85 +7,89 @@
       v-if="error"
       @click="getDevices"
     />
-    <template v-else>
-      <div class="l-flex__none l-flex--row">
-        <div class="l-flex__auto" />
-        <search-input
-          v-model.trim="deviceName"
-          class="l-flex__none c-sibling-item"
-          placeholder="设备名称"
-          @search="search"
-        />
-        <button
-          class="l-flex__none c-sibling-item o-button"
-          @click="search"
-        >
-          搜索
-        </button>
-      </div>
-      <div
-        class="l-flex__none l-flex--row c-tree__content c-tree__title u-pointer"
-        @click="toggleAllChange"
-      >
-        <span class="l-flex__auto">全部设备</span>
-        <el-checkbox
-          v-model="isAll"
-          :indeterminate="isIndeterminate"
-          class="l-flex__none"
-          @change="onAllChange"
-          @click.native.stop
-        />
-      </div>
-      <div class="l-flex__auto l-flex--col c-tree__list">
+    <template v-else-if="!loading">
+      <template v-if="groups.length">
+        <div class="l-flex__none l-flex--row has-bottom-padding">
+          <div class="l-flex__auto" />
+          <search-input
+            v-model.trim="deviceName"
+            class="l-flex__none c-sibling-item"
+            placeholder="设备名称"
+            @search="onSearch"
+          />
+          <button
+            class="l-flex__none c-sibling-item o-button"
+            @click="onSearch"
+          >
+            搜索
+          </button>
+        </div>
         <div
-          v-for="group in groups"
-          :key="group.id"
-          class="l-flex__none"
+          class="l-flex__none l-flex--row c-tree__title c-tree__content u-pointer"
+          @click="onAllToggle"
         >
+          <span class="l-flex__auto">全部设备</span>
+          <el-checkbox
+            :value="isAll"
+            :indeterminate="isIndeterminate"
+            class="l-flex__none c-tree__checkbox"
+          />
+        </div>
+        <div class="l-flex__auto l-flex--col c-tree__list u-overflow-y--auto">
           <div
-            class="c-tree__content u-pointer"
-            @click="expand(group)"
-          >
-            <i
-              class="c-tree__expand el-icon-arrow-up"
-              :class="{ expand: group.expand }"
-            />
-            <span class="c-tree__label">{{ group.name }}</span>
-            <el-checkbox
-              v-model="group.all"
-              class="l-flex__none"
-              :indeterminate="group.indeterminate"
-              :disabled="group.empty"
-              @change="onGroupAllChange(group)"
-              @click.native.stop
-            />
-          </div>
-          <div
-            v-show="group.expand"
-            class="c-tree__list"
+            v-for="group in groups"
+            :key="group.id"
+            class="l-flex__none"
           >
             <div
-              v-if="group.empty"
-              class="c-tree__empty"
-            >
-              暂无设备
-            </div>
-            <div
-              v-for="device in group.list"
-              :key="device.id"
               class="c-tree__content u-pointer"
-              @click="onDeviceToggle(group, device)"
+              @click="onGroupToggle(group)"
             >
-              <span class="c-tree__label">{{ device.name }} {{ showRatio ? device.resolutionRatio : '' }}</span>
+              <i
+                class="c-tree__expand el-icon-arrow-right"
+                :class="{ expand: group.expand }"
+              />
+              <span class="c-tree__label">{{ group.name }}</span>
               <el-checkbox
-                v-model="device.checked"
+                v-model="group.all"
                 class="l-flex__none"
-                @change="onDeviceChange(group, device)"
+                :indeterminate="group.indeterminate"
+                :disabled="group.empty"
+                @change="onGroupAllChange(group)"
                 @click.native.stop
               />
             </div>
+            <div
+              v-show="group.expand"
+              class="c-tree__list"
+            >
+              <div
+                v-if="group.empty"
+                class="c-tree__list-empty"
+              >
+                暂无设备
+              </div>
+              <div
+                v-for="device in group.list"
+                :key="device.id"
+                class="c-tree__content u-pointer"
+                @click="onDeviceToggle(group, device)"
+              >
+                <span class="c-tree__label">{{ device.name }} {{ showRatio ? device.resolutionRatio : '' }}</span>
+                <el-checkbox
+                  :value="device.checked"
+                  class="l-flex__none c-tree__checkbox"
+                />
+              </div>
+            </div>
           </div>
         </div>
+      </template>
+      <div
+        v-else
+        class="c-tree__empty"
+      >
+        暂无设备
       </div>
     </template>
   </div>
@@ -95,7 +99,7 @@
 import { getDeviceTree } from '@/api/device'
 
 export default {
-  name: 'DeviceTree',
+  name: 'DeviceGroupTree',
   props: {
     showRatio: {
       type: [Boolean, String],
@@ -133,10 +137,8 @@ export default {
         )
       ] : [])
     },
-    expand (group) {
-      group.expand = !group.expand
-    },
-    onAllChange () {
+    onAllToggle () {
+      this.isAll = !this.isAll
       this.isIndeterminate = false
       const checked = this.isAll
       this.groups.forEach(group => {
@@ -150,9 +152,8 @@ export default {
       })
       this.emitChange()
     },
-    toggleAllChange () {
-      this.isAll = !this.isAll
-      this.onAllChange()
+    onGroupToggle (group) {
+      group.expand = !group.expand
     },
     onGroupAllChange (group) {
       group.indeterminate = false
@@ -184,16 +185,19 @@ export default {
     getDevices () {
       this.loading = true
       this.error = false
-      getDeviceTree().then(({ data }) => {
-        this.$groups = data
-        this.search()
-      }, () => {
-        this.error = true
-      }).finally(() => {
+      getDeviceTree().then(
+        ({ data }) => {
+          this.$groups = data
+          this.onSearch()
+        },
+        () => {
+          this.error = true
+        }
+      ).finally(() => {
         this.loading = false
       })
     },
-    search () {
+    onSearch () {
       this.isAll = false
       this.isIndeterminate = false
       const regx = this.deviceName ? new RegExp(this.deviceName) : null
@@ -219,82 +223,8 @@ export default {
     },
     reset () {
       this.deviceName = ''
-      this.search()
+      this.onSearch()
     }
   }
 }
 </script>
-
-<style lang="scss" scoped>
-.o-title {
-  padding: 6px 6px 6px 0;
-  margin: 32px 0 12px;
-  color: $black;
-  font-size: 20px;
-  font-weight: bold;
-
-  &:hover {
-    background-color: $blue--light;
-  }
-}
-
-.c-tree {
-  color: $black;
-  font-size: 16px;
-
-  &.list {
-    .c-tree__title {
-      margin: 6px 0 0;
-    }
-  }
-
-  &__title {
-    margin: 32px 0 12px;
-    color: $black;
-    font-size: 20px;
-    font-weight: bold;
-  }
-
-  &__list {
-    overflow-y: auto;
-  }
-
-  &__content {
-    display: flex;
-    align-items: center;
-    padding: 6px 6px 6px 0;
-
-    &:hover {
-      background-color: $blue--light;
-    }
-  }
-
-  &__expand {
-    flex: none;
-    display: inline-flex;
-    justify-content: center;
-    align-items: center;
-    width: 30px;
-    transition: transform 0.4s;
-
-    &.expand {
-      transform: rotate(180deg);
-    }
-  }
-
-  &__label {
-    flex: auto;
-    padding-right: 10px;
-  }
-
-  &__empty {
-    padding: 6px 0 6px 40px;
-    color: $gray;
-    font-size: 12px;
-  }
-
-  &__list > &__content {
-    padding-left: 30px;
-  }
-}
-</style>

+ 6 - 81
src/components/DeviceTree/index.vue → src/components/tree/DeviceTree/index.vue

@@ -8,7 +8,7 @@
       @click="getDevices"
     />
     <template v-else-if="!loading">
-      <div class="l-flex__none l-flex--row">
+      <div class="l-flex__none l-flex--row has-bottom-padding">
         <div class="l-flex__auto" />
         <search-input
           v-model.trim="deviceName"
@@ -25,7 +25,7 @@
       </div>
       <template v-if="devices.length">
         <div
-          class="l-flex__none l-flex--row c-tree__content c-tree__title u-pointer"
+          class="l-flex__none l-flex--row c-tree__title c-tree__content u-pointer"
           @click="onAllToggle"
         >
           <span class="l-flex__auto">全部设备</span>
@@ -35,7 +35,7 @@
             class="l-flex__none c-tree__checkbox"
           />
         </div>
-        <div class="l-flex__auto l-flex--col c-tree__list">
+        <div class="l-flex__auto l-flex--col c-tree__list u-overflow-y--auto">
           <div
             v-for="device in devices"
             :key="device.id"
@@ -95,13 +95,14 @@ export default {
     getDevices () {
       this.loading = true
       this.error = false
+      this.isAll = false
+      this.isIndeterminate = false
+      this.emitChange()
       this.fetchDevices().then(
         data => {
           data.forEach(device => {
             device.checked = false
           })
-          this.isAll = false
-          this.isIndeterminate = false
           this.devices = data
         },
         () => {
@@ -145,79 +146,3 @@ export default {
   }
 }
 </script>
-
-<style lang="scss" scoped>
-.o-title {
-  padding: 6px 6px 6px 0;
-  margin: 32px 0 12px;
-  color: $black;
-  font-size: 20px;
-  font-weight: bold;
-
-  &:hover {
-    background-color: $blue--light;
-  }
-}
-
-.c-tree {
-  color: $black;
-  font-size: 16px;
-
-  &.list {
-    .c-tree__title {
-      margin: 6px 0 0;
-    }
-  }
-
-  &__title {
-    margin: 32px 0 12px;
-    color: $black;
-    font-size: 20px;
-    font-weight: bold;
-  }
-
-  &__list {
-    overflow-y: auto;
-  }
-
-  &__content {
-    display: flex;
-    align-items: center;
-    padding: 6px 6px 6px 0;
-
-    &:hover {
-      background-color: $blue--light;
-    }
-  }
-
-  &__expand {
-    flex: none;
-    display: inline-flex;
-    justify-content: center;
-    align-items: center;
-    width: 30px;
-    transition: transform 0.4s;
-
-    &.expand {
-      transform: rotate(180deg);
-    }
-  }
-
-  &__label {
-    flex: auto;
-    padding-right: 10px;
-  }
-
-  &__empty {
-    padding: $spacing;
-    color: $black;
-    font-size: 16px;
-    font-weight: bold;
-    text-align: center;
-  }
-
-  &__checkbox {
-    pointer-events: none;
-  }
-}
-</style>

+ 6 - 6
src/router/index.js

@@ -190,12 +190,12 @@ export const asyncRoutes = [
           }
         ]
       },
-      // {
-      //   name: 'group',
-      //   path: 'group',
-      //   component: () => import('@/views/device/group/index'),
-      //   meta: { title: '分组管理' }
-      // },
+      {
+        name: 'group',
+        path: 'group',
+        component: () => import('@/views/device/group/index'),
+        meta: { title: '分组管理' }
+      },
       {
         name: 'back',
         path: 'back',

+ 62 - 0
src/scss/bem/_component.scss

@@ -425,3 +425,65 @@
     overflow-x: auto;
   }
 }
+
+.c-tree {
+  color: $black;
+  font-size: 16px;
+
+  &__title {
+    margin: 0 0 12px;
+    color: $black;
+    font-size: 20px;
+    font-weight: bold;
+  }
+
+  &__content {
+    display: flex;
+    align-items: center;
+    padding: 6px 6px 6px 0;
+
+    &:hover {
+      background-color: $blue--light;
+    }
+  }
+
+  &__list > &__content {
+    padding-left: 30px;
+  }
+
+  &__expand {
+    flex: none;
+    display: inline-flex;
+    justify-content: center;
+    align-items: center;
+    width: 30px;
+    transition: transform 0.4s;
+
+    &.expand {
+      transform: rotate(90deg);
+    }
+  }
+
+  &__label {
+    flex: auto;
+    padding-right: 10px;
+  }
+
+  &__checkbox {
+    pointer-events: none;
+  }
+
+  &__list-empty {
+    padding: 6px 0 6px 30px;
+    color: $info;
+    font-size: 12px;
+  }
+
+  &__empty {
+    padding: $spacing;
+    color: $black;
+    font-size: 16px;
+    font-weight: bold;
+    text-align: center;
+  }
+}

+ 5 - 5
src/views/device/group/index.vue

@@ -42,7 +42,7 @@
       title="添加设备"
       :schema="deviceSchema"
       append-to-body
-      @choosen="onChooseDevice"
+      @choosen="onChoosenDevice"
     />
   </wrapper>
 </template>
@@ -98,9 +98,9 @@ export default {
           { prop: 'serialNumber', label: '序列号' },
           { prop: 'mac', label: 'MAC' },
           { prop: 'resolutionRatio', label: '分辨率' },
-          { prop: 'remark', label: '备注' },
+          { prop: 'remark', label: '地址' },
           {
-            type: 'invoke', render: [
+            type: 'invoke', width: 100, render: [
               { label: '移除', on: this.onDelDevice }
             ]
           }
@@ -118,7 +118,7 @@ export default {
           { prop: 'serialNumber', label: '序列号' },
           { prop: 'mac', label: 'MAC' },
           { prop: 'resolutionRatio', label: '分辨率' },
-          { prop: 'remark', label: '备注' }
+          { prop: 'remark', label: '地址' }
         ]
       }
     }
@@ -195,7 +195,7 @@ export default {
     onAddDevice () {
       this.$refs.deviceDialog.show()
     },
-    onChooseDevice ({ value: { id }, done }) {
+    onChoosenDevice ({ value: { id }, done }) {
       const table = this.$refs.subDeviceDialog.getTable()
       addDeviceToGroup(table.getCondition().id, id).then(() => {
         done()

+ 1 - 1
src/views/schedule/deploy/index.vue

@@ -31,7 +31,7 @@
       </button>
     </div>
     <div class="l-flex__fill l-flex">
-      <device-tree
+      <device-group-tree
         v-show="active === 0"
         ref="tree"
         class="l-flex__fill has-padding"