ソースを参照

feat(camera): 增加区域筛选及表单区域选择功能

yusheng 3 週間 前
コミット
42540f7867

+ 308 - 223
src/views/ledgerAssets/camera/components/formModel.vue

@@ -42,6 +42,16 @@
       </el-row> -->
 
       <el-row :gutter="15">
+        <el-col :span="8">
+          <el-form-item label="所属区域" prop="areaId">
+            <area-select
+              v-model="form.areaId"
+              @checkedKeys="getAreaInfo"
+              :data="areaTreeList"
+              ref="areaTree"
+            />
+          </el-form-item>
+        </el-col>
         <el-col :span="8">
           <el-form-item label="摄像机编号" prop="deviceCode">
             <el-input
@@ -62,14 +72,18 @@
             ></DictSelection>
           </el-form-item>
         </el-col>
+      </el-row>
+
+      <el-row :gutter="15">
         <el-col :span="8">
           <el-form-item label="摄像机名称" prop="name">
-            <el-input v-model="form.name" placeholder="请输入" :maxlength="20" />
+            <el-input
+              v-model="form.name"
+              placeholder="请输入"
+              :maxlength="20"
+            />
           </el-form-item>
         </el-col>
-      </el-row>
-
-      <el-row :gutter="15">
         <el-col :span="8">
           <el-form-item label="品牌" prop="brandCode">
             <DictSelection
@@ -105,7 +119,11 @@
         </el-col>
         <el-col :span="8">
           <el-form-item label="状态" prop="activityStatus">
-            <el-radio-group v-model="form.activityStatus" class="ml-4" style="flex-wrap: nowrap">
+            <el-radio-group
+              v-model="form.activityStatus"
+              class="ml-4"
+              style="flex-wrap: nowrap"
+            >
               <el-radio :label="1">启用</el-radio>
               <el-radio :label="0">停用</el-radio>
             </el-radio-group>
@@ -117,7 +135,11 @@
       <el-row :gutter="15">
         <el-col :span="8">
           <el-form-item label="IP" prop="extraInfo.ip">
-            <el-input v-model="form.extraInfo.ip" placeholder="请输入" :maxlength="20" />
+            <el-input
+              v-model="form.extraInfo.ip"
+              placeholder="请输入"
+              :maxlength="20"
+            />
           </el-form-item>
         </el-col>
         <el-col :span="8">
@@ -138,12 +160,20 @@
       <el-row :gutter="15">
         <el-col :span="8">
           <el-form-item label="账号" prop="extraInfo.account">
-            <el-input v-model="form.extraInfo.account" placeholder="请输入" :maxlength="30" />
+            <el-input
+              v-model="form.extraInfo.account"
+              placeholder="请输入"
+              :maxlength="30"
+            />
           </el-form-item>
         </el-col>
         <el-col :span="8">
           <el-form-item label="密码" prop="extraInfo.password">
-            <el-input v-model="form.extraInfo.password" placeholder="请输入" :maxlength="30" />
+            <el-input
+              v-model="form.extraInfo.password"
+              placeholder="请输入"
+              :maxlength="30"
+            />
           </el-form-item>
         </el-col>
       </el-row>
@@ -161,7 +191,11 @@
         </el-col>
         <el-col :span="8">
           <el-form-item label="支持云台控制" prop="extraInfo.ptzControl">
-            <el-radio-group v-model="form.extraInfo.ptzControl" class="ml-4" style="flex-wrap: nowrap">
+            <el-radio-group
+              v-model="form.extraInfo.ptzControl"
+              class="ml-4"
+              style="flex-wrap: nowrap"
+            >
               <el-radio :label="0">支持</el-radio>
               <el-radio :label="1">不支持</el-radio>
             </el-radio-group>
@@ -202,246 +236,297 @@
 </template>
 
 <script>
-import dictMixins from '@/mixins/dictMixins';
-import * as CameraApi from '@/api/ledgerAssets/camera'
-import * as DeviceApi from '@/api/ledgerAssets/device'
-import * as AreaApi from '@/api/basic/area'
-import { getCode } from '@/api/ruleManagement/matter';
-// import { handleTree } from '@/utils/tree'
-// import { getStationData } from '@/utils/auth'
-
-const defForm = {
-  name: '',
-  deviceCode: '',
-  classifyCode: '',
-  classifyName: '',
-  modelId: '',
-  modelName: '',
-  brandCode: '',
-  brandName: '',
-  // stationName: '',
-  // stationId: '',
-  // areaId: '',
-  // areaCode: '',
-  // areaName: '',
-  // byNvrCode: '',
-  // byNvrName: '',
-  deviceSort: 100,
-  activityStatus: 1,
-  relDeviceType: '',
-  relDeviceId: '',
-  delayTime: '',
-  listLoad: [],
-  extInfo: '{}',
-  extraInfo: {
-    ip: '',
-    port: 8000,
-    account: 'admin',
-    password: 'admin',
-    ptzControl: 0,
-    stream: '',
-    channel: '',
-    // nvr: ''
-  }
-}
+  import dictMixins from '@/mixins/dictMixins';
+  import * as CameraApi from '@/api/ledgerAssets/camera';
+  import * as DeviceApi from '@/api/ledgerAssets/device';
+  import * as AreaApi from '@/api/basic/area';
+  import { basicAreaPageAPI } from '@/api/factoryModel';
+  import { getCode } from '@/api/ruleManagement/matter';
+  import areaSelect from '@/views/ledgerAssets/components/area-select.vue';
+  // import { handleTree } from '@/utils/tree'
+  // import { getStationData } from '@/utils/auth'
 
-export default {
-  name: 'CameraForm',
-  mixins: [dictMixins],
-  data() {
-    return {
-      visible: false,
-      title: '',
-      loading: false,
-      saving: false,
-      type: '',
-      areaTree: [],
-      loadNvrDeviceList: [],
-      loadDeviceList: [],
-      defaultProps: {
-        children: 'children',
-        label: 'name'
-      },
-      form: { ...defForm },
-      rules: {
-        name: [{ required: true, message: '摄像机名称不能为空', trigger: 'blur' }],
-        deviceCode: [{ required: true, message: '摄像机编号不能为空', trigger: 'blur' }],
-        brandCode: [{ required: true, message: '品牌不能为空', trigger: 'change' }],
-        classifyCode: [{ required: true, message: '摄像机类型不能为空', trigger: 'change' }],
-        deviceSort: [{ required: true, message: '排序号不能为空', trigger: 'change' }],
-        stationName: [{ required: true, message: '所属场站不能为空', trigger: 'change' }],
-        areaId: [{ required: true, message: '所属区域不能为空', trigger: 'change' }],
-        extraInfo: {
-          ip: [{ required: true, message: 'IP不能为空', trigger: 'blur' }],
-          port: [{ required: true, message: '端口不能为空', trigger: 'blur' }],
-          account: [{ required: true, message: '账号不能为空', trigger: 'blur' }],
-          password: [{ required: true, message: '密码不能为空', trigger: 'blur' }],
-          channel: [{ required: true, message: '通道号不能为空', trigger: 'blur' }],
-          stream: [{ required: true, message: 'RTSP流不能为空', trigger: 'blur' }]
-        }
-      }
+  const defForm = {
+    name: '',
+    deviceCode: '',
+    classifyCode: '',
+    classifyName: '',
+    modelId: '',
+    modelName: '',
+    brandCode: '',
+    brandName: '',
+    stationName: '',
+    stationId: '',
+    areaId: '',
+    areaCode: '',
+    areaName: '',
+    // byNvrCode: '',
+    // byNvrName: '',
+    deviceSort: 100,
+    activityStatus: 1,
+    relDeviceType: '',
+    relDeviceId: '',
+    delayTime: '',
+    listLoad: [],
+    extInfo: '{}',
+    extraInfo: {
+      ip: '',
+      port: 8000,
+      account: 'admin',
+      password: 'admin',
+      ptzControl: 0,
+      stream: '',
+      channel: ''
+      // nvr: ''
     }
-  },
-  created() {
-    this.requestDict('摄像头品牌');
-    // this.requestDict('NVR设备类型');
-    this.requestDict('摄像机类型');
-  },
-  methods: {
-    brandCodeChange(e) {
-      console.log('brandCodeChange', e)
-      this.form.brandName = e.dictValue;
+  };
+
+  export default {
+    name: 'CameraForm',
+    mixins: [dictMixins],
+    components: {
+      areaSelect
     },
-    classifyCodeChange(e) {
-      console.log('classifyCodeChange', e)
-      this.form.classifyName = e.dictValue;
+    data() {
+      return {
+        visible: false,
+        title: '',
+        loading: false,
+        saving: false,
+        type: '',
+        areaTree: [],
+        areaTreeList: [],
+        loadNvrDeviceList: [],
+        loadDeviceList: [],
+        defaultProps: {
+          children: 'children',
+          label: 'name'
+        },
+        form: { ...defForm },
+        rules: {
+          name: [
+            { required: true, message: '摄像机名称不能为空', trigger: 'blur' }
+          ],
+          deviceCode: [
+            { required: true, message: '摄像机编号不能为空', trigger: 'blur' }
+          ],
+          brandCode: [
+            { required: true, message: '品牌不能为空', trigger: 'change' }
+          ],
+          classifyCode: [
+            { required: true, message: '摄像机类型不能为空', trigger: 'change' }
+          ],
+          deviceSort: [
+            { required: true, message: '排序号不能为空', trigger: 'change' }
+          ],
+          stationName: [
+            { required: true, message: '所属场站不能为空', trigger: 'change' }
+          ],
+          areaId: [
+            { required: true, message: '所属区域不能为空', trigger: 'change' }
+          ],
+          extraInfo: {
+            ip: [{ required: true, message: 'IP不能为空', trigger: 'blur' }],
+            port: [
+              { required: true, message: '端口不能为空', trigger: 'blur' }
+            ],
+            account: [
+              { required: true, message: '账号不能为空', trigger: 'blur' }
+            ],
+            password: [
+              { required: true, message: '密码不能为空', trigger: 'blur' }
+            ],
+            channel: [
+              { required: true, message: '通道号不能为空', trigger: 'blur' }
+            ],
+            stream: [
+              { required: true, message: 'RTSP流不能为空', trigger: 'blur' }
+            ]
+          }
+        }
+      };
     },
-    /** 加载NVR设备列表 */
-    loadNvrDeviceData() {
-      DeviceApi.getDeviceList({ classifyCode: '' }).then((res) => {
-        this.loadNvrDeviceList = res
-      })
+    created() {
+      this.requestDict('摄像头品牌');
+      // this.requestDict('NVR设备类型');
+      this.requestDict('摄像机类型');
     },
+    methods: {
+      brandCodeChange(e) {
+        console.log('brandCodeChange', e);
+        this.form.brandName = e.dictValue;
+      },
+      classifyCodeChange(e) {
+        console.log('classifyCodeChange', e);
+        this.form.classifyName = e.dictValue;
+      },
+      /** 加载NVR设备列表 */
+      loadNvrDeviceData() {
+        DeviceApi.getDeviceList({ classifyCode: '' }).then((res) => {
+          this.loadNvrDeviceList = res;
+        });
+      },
 
-    /** 获得区域树 */
-    getAreaTree(stationId) {
-      AreaApi.getAreaList({ stationId: stationId }).then((res) => {
-        // this.areaTree = handleTree(res)
-        console.log('getAreaTree', res)
-        this.areaTree = this.$util.toTreeData({
-              data: res.list,
-              idField: 'id',
-              parentIdField: 'parentId'
-            });
-      })
-    },
+      /** 获得区域树 */
+      getAreaTree(stationId) {
+        AreaApi.getAreaList({ stationId: stationId }).then((res) => {
+          // this.areaTree = handleTree(res)
+          console.log('getAreaTree', res);
+          this.areaTree = this.$util.toTreeData({
+            data: res.list,
+            idField: 'id',
+            parentIdField: 'parentId'
+          });
+        });
+      },
 
-    /** 品牌change事件 */
-    brandChange(e) {
-      this.form.brandName = this.getDictValue('摄像头品牌', e+'')
-    },
+      /** 获取区域树列表 */
+      getBasicAreaList() {
+        basicAreaPageAPI({
+          pageNum: 1,
+          size: 9999
+        }).then((list) => {
+          this.areaTreeList = this.$util.toTreeData({
+            data: list || [],
+            idField: 'id',
+            parentIdField: 'parentId'
+          });
+        });
+      },
 
-    /** 设备分类Change事件 */
-    handleClassifyId(e) {
-      this.form.classifyName = this.getDictValue('摄像机类型', e)
-    },
+      /** 区域选择回调 */
+      getAreaInfo(nodeInfo) {
+        if (nodeInfo) {
+          this.form.areaId = nodeInfo.id;
+          this.form.areaName = nodeInfo.name;
+          this.form.areaCode = nodeInfo.areaCode;
+        }
+      },
 
-    /** 关联NVR设备Change事件 */
-    handleNvr(val) {
-      const deviceObj = this.loadNvrDeviceList.find((item) => item.deviceCode == val)
-      if (deviceObj) {
-        this.form.byNvrName = deviceObj.name
-      } else {
-        this.form.byNvrName = ''
-      }
-    },
+      /** 品牌change事件 */
+      brandChange(e) {
+        this.form.brandName = this.getDictValue('摄像头品牌', e + '');
+      },
 
-    /** 区域Change事件 */
-    areaIdChange(e) {
-      this.processingAreaId(e, this.areaTree)
-    },
+      /** 设备分类Change事件 */
+      handleClassifyId(e) {
+        this.form.classifyName = this.getDictValue('摄像机类型', e);
+      },
 
-    processingAreaId(id, data) {
-      for (let i = 0; i < data.length; i++) {
-        if (data[i].id == id) {
-          this.form.areaCode = data[i].areaCode
-          this.form.areaName = data[i].name
-          return
+      /** 关联NVR设备Change事件 */
+      handleNvr(val) {
+        const deviceObj = this.loadNvrDeviceList.find(
+          (item) => item.deviceCode == val
+        );
+        if (deviceObj) {
+          this.form.byNvrName = deviceObj.name;
         } else {
-          if (data[i].children && data[i].children.length) {
-            this.processingAreaId(id, data[i].children)
-          }
+          this.form.byNvrName = '';
         }
-      }
-    },
-
-    /** 打开弹窗 */
-    open(type, id, station) {
-      this.type = type
-      this.title = type === 'create' ? '新增摄像机' : '编辑摄像机'
+      },
 
-      // 重置表单
-      this.form = { ...defForm }
-      // this.loadNvrDeviceData()
+      /** 区域Change事件 */
+      areaIdChange(e) {
+        this.processingAreaId(e, this.areaTree);
+      },
 
-      // 设置场站信息
-      // const stationData = getStationData()
-      // this.getAreaTree(this.form.stationId)
-      if (station) {
-        this.form.stationName = station.stationName
-        this.form.stationId = station.stationId || station.id
-        this.getAreaTree(this.form.stationId)
-        if (station.stationId) {
-          this.form.areaCode = station.areaCode
-          this.form.areaName = station.areaName
-          this.form.areaId = station.id
+      processingAreaId(id, data) {
+        for (let i = 0; i < data.length; i++) {
+          if (data[i].id == id) {
+            this.form.areaCode = data[i].areaCode;
+            this.form.areaName = data[i].name;
+            return;
+          } else {
+            if (data[i].children && data[i].children.length) {
+              this.processingAreaId(id, data[i].children);
+            }
+          }
         }
-      }
-      //  else if (stationData) {
-      //   this.form.stationName = stationData.stationName
-      //   this.form.stationId = stationData.stationId || stationData.id
-      // }
+      },
 
-      // 编辑时,加载数据
-      if (id) {
-        this.loading = true
-        CameraApi.getDevice(id)
-          .then((res) => {
-            this.form = res
-          })
-          .finally(() => {
-            this.loading = false
-          })
-      } else {
-        // 新增时生成编号
-        getCode('camera_code').then((code) => {
-          this.form.deviceCode = code
-        })
-      }
+      /** 打开弹窗 */
+      open(type, id, areaInfo) {
+        this.type = type;
+        this.title = type === 'create' ? '新增摄像机' : '编辑摄像机';
 
-      this.visible = true
-    },
+        // 重置表单
+        this.form = { ...defForm };
+        // this.loadNvrDeviceData()
 
-    /** 取消 */
-    cancel() {
-      this.form = { ...defForm }
-      this.visible = false
-    },
+        // 加载区域树
+        this.getBasicAreaList();
 
-    /** 保存 */
-    save() {
-      this.$refs.form.validate((valid) => {
-        if (valid) {
-          this.saving = true
-          const data = { ...this.form }
-          const action =
-            this.type === 'create' ? CameraApi.createDevice(data) : CameraApi.updateDevice(data)
+        // 从列表页左侧区域树带入所选区域
+        if (areaInfo && areaInfo.id) {
+          this.form.areaId = areaInfo.id;
+          this.form.areaName = areaInfo.name;
+          this.form.areaCode = areaInfo.areaCode;
+        }
 
-          action
-            .then(() => {
-              this.$message.success(this.type === 'create' ? '新增成功' : '修改成功')
-              this.cancel()
-              this.$emit('success')
-            })
-            .catch((e) => {
-              this.$message.error(e.message)
+        // 编辑时,加载数据
+        if (id) {
+          this.loading = true;
+          CameraApi.getDevice(id)
+            .then((res) => {
+              this.form = res;
             })
             .finally(() => {
-              this.saving = false
-            })
+              this.loading = false;
+            });
+        } else {
+          // 新增时生成编号
+          getCode('camera_code').then((code) => {
+            this.form.deviceCode = code;
+          });
         }
-      })
+
+        this.visible = true;
+      },
+
+      /** 取消 */
+      cancel() {
+        this.form = { ...defForm };
+        this.visible = false;
+      },
+
+      /** 保存 */
+      save() {
+        this.$refs.form.validate((valid) => {
+          if (valid) {
+            this.saving = true;
+            const data = { ...this.form };
+            const action =
+              this.type === 'create'
+                ? CameraApi.createDevice(data)
+                : CameraApi.updateDevice(data);
+
+            action
+              .then(() => {
+                this.$message.success(
+                  this.type === 'create' ? '新增成功' : '修改成功'
+                );
+                this.cancel();
+                this.$emit('success');
+              })
+              .catch((e) => {
+                this.$message.error(e.message);
+              })
+              .finally(() => {
+                this.saving = false;
+              });
+          }
+        });
+      }
     }
-  }
-}
+  };
 </script>
 
 <style lang="scss" scoped>
-.tit {
-  margin-left: 10px;
-  font-weight: bold;
-  border-left: 3px solid #9266f9;
-  padding-left: 10px;
-  margin-bottom: 14px;
-}
+  .tit {
+    margin-left: 10px;
+    font-weight: bold;
+    border-left: 3px solid #9266f9;
+    padding-left: 10px;
+    margin-bottom: 14px;
+  }
 </style>

+ 171 - 77
src/views/ledgerAssets/camera/index.vue

@@ -1,79 +1,106 @@
 <template>
   <div class="ele-body">
-    <el-card shadow="never">
-      <!-- 搜索表单 -->
-      <camera-search ref="searchRef" @search="reload" />
-      <!-- 数据表格 -->
-      <ele-pro-table
-      :page-size="defPageSize"
-        ref="table"
-        :columns="columns"
-        :datasource="datasource"
-        :selection.sync="selection"
-        :cache-key="cacheKeyUrl"
-        :pageSizes="tablePageSizes"
-        :response="{
-          dataName: 'data.records', // 数据列表的字段名称,支持嵌套,例如:data.rows
-          countName: 'data.total' // 数据总数的字段名称,例如:data.total
-        }"
+    <el-card shadow="never" v-loading="loading">
+      <ele-split-layout
+        width="266px"
+        allow-collapse
+        :right-style="{ overflow: 'hidden' }"
       >
-        <!-- 表头工具栏 -->
-        <template v-slot:toolbar>
-          <el-button
-            type="primary"
-            icon="el-icon-plus"
-            class="ele-btn-icon"
-            v-if="$hasPermission('ledgerAssets:camera:create')"
-            @click="openForm('create')"
+        <div>
+          <div class="ele-border-lighter sys-organization-list">
+            <div class="tree-title">区域列表</div>
+            <el-tree
+              ref="areaTree"
+              :data="areaTreeList"
+              :props="defaultProps"
+              node-key="id"
+              highlight-current
+              default-expand-all
+              :expand-on-click-node="false"
+              @node-click="handleAreaClick"
+            >
+            </el-tree>
+          </div>
+        </div>
+        <template v-slot:content>
+          <!-- 搜索表单 -->
+          <camera-search ref="searchRef" @search="reload" />
+          <!-- 数据表格 -->
+          <ele-pro-table
+            :page-size="defPageSize"
+            ref="table"
+            :columns="columns"
+            :datasource="datasource"
+            :selection.sync="selection"
+            :cache-key="cacheKeyUrl"
+            :pageSizes="tablePageSizes"
+            height="calc(100vh - 320px)"
+            full-height="calc(100vh - 115px)"
+            :response="{
+              dataName: 'data.records', // 数据列表的字段名称,支持嵌套,例如:data.rows
+              countName: 'data.total' // 数据总数的字段名称,例如:data.total
+            }"
           >
-            新建
-          </el-button>
-          <el-button
-            type="danger"
-            icon="el-icon-delete"
-            class="ele-btn-icon"
-            v-if="
-              $hasPermission('ledgerAssets:camera:delete') && selection.length
-            "
-            @click="handleBatchDelete"
-          >
-            批量删除
-          </el-button>
-        </template>
+            <!-- 表头工具栏 -->
+            <template v-slot:toolbar>
+              <el-button
+                type="primary"
+                icon="el-icon-plus"
+                class="ele-btn-icon"
+                v-if="$hasPermission('ledgerAssets:camera:create')"
+                @click="openForm('create')"
+              >
+                新建
+              </el-button>
+              <el-button
+                type="danger"
+                icon="el-icon-delete"
+                class="ele-btn-icon"
+                v-if="
+                  $hasPermission('ledgerAssets:camera:delete') &&
+                  selection.length
+                "
+                @click="handleBatchDelete"
+              >
+                批量删除
+              </el-button>
+            </template>
 
-        <!-- 摄像机状态列 -->
-        <template v-slot:activityStatus="{ row }">
-          <el-switch
-            v-model="row.activityStatus"
-            :active-value="1"
-            :inactive-value="0"
-            @change="handleStatusChange(row)"
-          />
-        </template>
+            <!-- 摄像机状态列 -->
+            <template v-slot:activityStatus="{ row }">
+              <el-switch
+                v-model="row.activityStatus"
+                :active-value="1"
+                :inactive-value="0"
+                @change="handleStatusChange(row)"
+              />
+            </template>
 
-        <!-- 操作列 -->
-        <template v-slot:action="{ row }">
-          <el-link
-            type="primary"
-            :underline="false"
-            icon="el-icon-edit"
-            v-if="$hasPermission('ledgerAssets:camera:update')"
-            @click="openForm('update', row.id)"
-          >
-            编辑
-          </el-link>
-          <el-link
-            type="primary"
-            :underline="false"
-            icon="el-icon-delete"
-            :style="{ color: delColor }"
-            v-if="$hasPermission('ledgerAssets:camera:delete')"
-            @click="handleDelete(row.id)"
-          >
-            删除
-          </el-link>
+            <!-- 操作列 -->
+            <template v-slot:action="{ row }">
+              <el-link
+                type="primary"
+                :underline="false"
+                icon="el-icon-edit"
+                v-if="$hasPermission('ledgerAssets:camera:update')"
+                @click="openForm('update', row.id)"
+              >
+                编辑
+              </el-link>
+              <el-link
+                type="primary"
+                :underline="false"
+                icon="el-icon-delete"
+                :style="{ color: delColor }"
+                v-if="$hasPermission('ledgerAssets:camera:delete')"
+                @click="handleDelete(row.id)"
+              >
+                删除
+              </el-link>
+            </template>
+          </ele-pro-table>
         </template>
-      </ele-pro-table>
+      </ele-split-layout>
     </el-card>
 
     <!-- 表单弹窗:添加/修改 -->
@@ -83,6 +110,7 @@
 
 <script>
   import * as CameraApi from '@/api/ledgerAssets/camera';
+  import { basicAreaPageAPI } from '@/api/factoryModel';
   import formModel from './components/formModel.vue';
   import cameraSearch from './components/camera-search.vue';
 
@@ -97,6 +125,15 @@
         cacheKeyUrl: 'ledgerCameraTable',
         delColor: '#F56C6C',
         selection: [],
+        loading: false,
+        // 当前选中的区域
+        currentArea: null,
+        // 区域树数据
+        areaTreeList: [],
+        defaultProps: {
+          children: 'children',
+          label: 'name'
+        },
         // 表格列配置
         columns: [
           {
@@ -131,6 +168,14 @@
             showOverflowTooltip: true,
             minWidth: 200
           },
+          {
+            prop: 'areaName',
+            label: '所属区域',
+            headerAlign: 'center',
+            align: 'center',
+            showOverflowTooltip: true,
+            minWidth: 160
+          },
           {
             prop: 'brandName',
             label: '设备品牌',
@@ -181,11 +226,41 @@
             slot: 'action',
             showOverflowTooltip: true
           }
-        ],
-        loading: false
+        ]
       };
     },
+    created() {
+      this.getAreaTreeList();
+    },
     methods: {
+      /* 获取区域树 */
+      getAreaTreeList() {
+        this.loading = true;
+        basicAreaPageAPI({
+          pageNum: 1,
+          size: 9999
+        })
+          .then((list) => {
+            this.areaTreeList = this.$util.toTreeData({
+              data: list || [],
+              idField: 'id',
+              parentIdField: 'parentId'
+            });
+          })
+          .finally(() => {
+            this.loading = false;
+          });
+      },
+
+      /* 点击区域节点查询 */
+      handleAreaClick(data) {
+        this.currentArea = data;
+        // 记录所选区域到搜索条件并刷新
+        this.reload({
+          areaId: data.id
+        });
+      },
+
       /* 表格数据源 */
       async datasource({ page, limit, where }) {
         return await CameraApi.getDevicePage({
@@ -193,10 +268,6 @@
           size: limit,
           ...where
         });
-
-        console.log('获取摄像机分页数据', res);
-
-        return res.data.records;
       },
 
       /* 刷新表格 */
@@ -206,7 +277,7 @@
 
       /** 添加/修改操作 */
       openForm(type, id) {
-        this.$refs.formRef.open(type, id);
+        this.$refs.formRef.open(type, id, this.currentArea);
       },
 
       /** 状态切换 */
@@ -268,4 +339,27 @@
   };
 </script>
 
-<style lang="scss" scoped></style>
+<style lang="scss" scoped>
+  .sys-organization-list {
+    position: absolute;
+    top: 0;
+    bottom: 0;
+    left: 0;
+    right: 0;
+    box-sizing: border-box;
+    border-width: 1px;
+    border-style: solid;
+    overflow: auto;
+  }
+  .tree-title {
+    padding: 10px 12px;
+    font-weight: bold;
+    border-bottom: 1px solid #ebeef5;
+  }
+  .sys-organization-list :deep(.el-tree-node__content) {
+    height: 36px;
+    & > .el-tree-node__expand-icon {
+      margin-left: 10px;
+    }
+  }
+</style>