| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180 |
- <template>
- <div class="device">
- <el-card shadow="never" style="border: 0" v-show="showSearch">
- <el-form
- class="search-form"
- :model="queryParams"
- ref="queryFormRef"
- inline
- style="margin-bottom: -20px"
- >
- <el-form-item label="设备名称" prop="deviceName">
- <el-input
- v-model="queryParams.deviceName"
- placeholder="请输入设备名称"
- clearable
- size="default"
- @keyup.enter="handleQuery"
- style="width: 130px"
- />
- </el-form-item>
- <el-form-item label="所在部门" prop="deptId">
- <el-tree-select
- v-model="queryParams.deptId"
- :data="deptList"
- :props="defaultProps"
- check-strictly
- node-key="id"
- filterable
- placeholder="请选择所在部门"
- @keyup.enter="handleQuery"
- style="width: 200px;"
- size="default"
- />
- </el-form-item>
- <el-form-item label="设备编号" prop="serialNumber">
- <el-input
- v-model="queryParams.serialNumber"
- placeholder="请输入设备编号"
- clearable
- size="default"
- @keyup.enter="handleQuery"
- style="width: 130px"
- />
- </el-form-item>
- <el-form-item label="设备状态" prop="status">
- <el-select
- v-model="queryParams.status"
- placeholder="请选择设备状态"
- clearable
- size="default"
- style="width: 130px"
- >
- <el-option
- v-for="dict in getStrDictOptions(DICT_TYPE.VIDEO_DEVICE_STATUS)"
- :key="dict.value"
- :label="dict.label"
- :value="dict.value"
- />
- </el-select>
- </el-form-item>
- <el-form-item>
- <el-button type="primary" :icon="Search" size="default" @click="handleQuery"
- >查询</el-button
- >
- <el-button :icon="Refresh" size="default" @click="resetQuery">重置</el-button>
-
- </el-form-item>
- </el-form>
- </el-card>
- <el-card
- class="main-card border-0!"
- shadow="never"
- v-if="showType == 'list'"
- :style="showSearch ? '' : 'margin:0'"
- style="border: 0;"
- >
- <div class="card-toolbar mb8">
- <div>
- <el-dropdown class="mr10" @command="handleCommand">
- <el-button size="small" type="primary" :icon="Plus">
- 新增
- <el-icon class="el-icon--right"><arrow-down /></el-icon>
- </el-button>
- <template #dropdown>
- <el-dropdown-menu>
- <el-dropdown-item command="handleEditDevice">手动添加</el-dropdown-item>
- <el-dropdown-item command="handleBatchImport">批量导入</el-dropdown-item>
- </el-dropdown-menu>
- </template>
- </el-dropdown>
- <!-- <el-dropdown @command="handleCommand1">
- <el-button size="default" type="primary">
- 分配设备
- <el-icon class="el-icon--right"><arrow-down /></el-icon>
- </el-button>
- <template #dropdown>
- <el-dropdown-menu>
- <el-dropdown-item command="handleSelectAllot">选择分配</el-dropdown-item>
- <el-dropdown-item command="handleImportAllot">导入分配</el-dropdown-item>
- </el-dropdown-menu>
- </template>
- </el-dropdown>
- <el-button type="primary" size="default" @click="recycleDevice" style="margin-left: 10px"
- >回收设备</el-button
- > -->
- </div>
- <div>
- <el-radio-group class="float-right ml-10" plain v-model="showType">
- <el-radio-button label="card"
- ><el-icon><Menu /></el-icon
- ></el-radio-button>
- <el-radio-button label="list"
- ><el-icon><Fold /></el-icon
- ></el-radio-button>
- </el-radio-group>
- <right-toolbar v-model:showSearch="showSearch" @query-table="getList" />
- </div>
- </div>
- <el-table class="base-table" v-loading="loading" :data="deviceList" :border="false">
- <el-table-column
- label="图标"
- align="center"
- header-align="center"
- prop="deviceId"
- width="72"
- >
- <template #default="{ row }">
- <el-image
- style="width: 100%; height: auto"
- lazy
- :preview-src-list="[baseUrl + row.imgUrl]"
- :src="baseUrl + row.imgUrl"
- fit="cover"
- v-if="row.imgUrl != null && row.imgUrl != ''"
- />
- <el-image
- style="width: 100%; height: auto"
- :preview-src-list="[gatewayImage]"
- :src="gatewayImage"
- fit="cover"
- v-else-if="row.deviceType == 2"
- />
- <el-image
- style="width: 100%; height: auto"
- :preview-src-list="[videoImage]"
- :src="videoImage"
- fit="cover"
- v-else-if="row.deviceType == 3"
- />
- <el-image
- style="width: 100%; height: auto"
- :preview-src-list="[productImage]"
- :src="productImage"
- fit="cover"
- v-else
- />
- </template>
- </el-table-column>
- <el-table-column
- label="编号"
- align="center"
- header-align="center"
- prop="deviceId"
- width="50"
- />
- <el-table-column label="设备名称" prop="deviceName" min-width="180" />
- <el-table-column label="设备编号" align="center" prop="serialNumber" min-width="130" />
- <el-table-column label="所属产品" align="center" prop="productName" min-width="160" />
- <el-table-column label="协议" align="center" prop="transport" min-width="80" />
- <el-table-column label="通讯协议" align="center" prop="protocolCode" min-width="140" />
- <el-table-column label="子设备数" align="center" prop="subDeviceCount" width="80">
- <template #default="scope">
- {{ scope.row.subDeviceCount }}
- </template>
- </el-table-column>
- <el-table-column label="设备影子" align="center" prop="isShadow" width="80">
- <template #default="scope">
- <el-tag type="success" size="default" v-if="scope.row.isShadow == 1">启用</el-tag>
- <el-tag type="info" size="default" v-else>禁用</el-tag>
- </template>
- </el-table-column>
- <el-table-column label="状态" align="center" prop="status" width="80">
- <template #default="scope">
- <dict-tag :type="DICT_TYPE.VIDEO_DEVICE_STATUS" :value="scope.row.status" />
- </template>
- </el-table-column>
- <el-table-column label="信号" align="center" prop="rssi" width="60">
- <template #default="scope">
- <svg-icon v-if="scope.row.status == 3 && scope.row.rssi >= '-55'" icon-class="wifi_4" />
- <svg-icon
- v-else-if="scope.row.status == 3 && scope.row.rssi >= '-70' && scope.row.rssi < '-55'"
- icon-class="wifi_3"
- />
- <svg-icon
- v-else-if="scope.row.status == 3 && scope.row.rssi >= '-85' && scope.row.rssi < '-70'"
- icon-class="wifi_2"
- />
- <svg-icon
- v-else-if="
- scope.row.status == 3 && scope.row.rssi >= '-100' && scope.row.rssi < '-85'
- "
- icon-class="wifi_1"
- />
- <svg-icon v-else icon-class="wifi_0" />
- </template>
- </el-table-column>
- <el-table-column label="定位方式" align="center" prop="locationWay" width="100">
- <template #default="scope">
- <dict-tag :type="DICT_TYPE.VIDEO_CENTER_LOCATION_WAY" :value="scope.row.locationWay" />
- </template>
- </el-table-column>
- <el-table-column label="固件版本" align="center" prop="firmwareVersion" width="100">
- <template #default="scope">
- <el-tag size="small" type="info">Ver {{ scope.row.firmwareVersion }}</el-tag>
- </template>
- </el-table-column>
- <el-table-column label="激活时间" align="center" prop="activeTime" width="100">
- <template #default="scope">
- <span>{{ parseTime(scope.row.activeTime, '{y}-{m}-{d}') }}</span>
- </template>
- </el-table-column>
- <el-table-column label="创建时间" align="center" prop="createTime" width="100">
- <template #default="scope">
- <span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d}') }}</span>
- </template>
- </el-table-column>
- <el-table-column
- label="操作"
- align="center"
- class-name="small-padding fixed-width"
- fixed="right"
- width="200"
- >
- <template #default="scope">
- <el-button
- type="danger"
- plain
- style="padding: 5px"
- :icon="Delete"
- @click="handleDelete(scope.row)"
- >删除</el-button
- >
- <el-button
- type="primary"
- plain
- style="padding: 5px"
- :icon="View"
- @click="handleEditDevice(scope.row)"
- >查看</el-button
- >
- <el-button
- type="primary"
- plain
- style="padding: 5px"
- @click="openSummaryDialog(scope.row)"
- v-if="form.deviceId != 0"
- >二维码</el-button
- >
- </template>
- </el-table-column>
- </el-table>
- <pagination
- v-show="total > 0"
- :total="total"
- v-model:page="queryParams.pageNum"
- v-model:limit="queryParams.pageSize"
- :page-sizes="[12, 24, 36, 60]"
- @pagination="getList"
- />
- </el-card>
- <el-card
- class="main-card"
- shadow="never"
- v-if="showType == 'card'"
- :style="showSearch ? '' : 'margin:0'"
- style="border: 0;"
- >
- <div class="card-toolbar mb8">
- <div>
- <el-dropdown class="mr10" @command="handleCommand">
- <el-button size="small" type="primary" :icon="Plus">
- 新增
- <el-icon class="el-icon--right"><arrow-down /></el-icon>
- </el-button>
- <template #dropdown>
- <el-dropdown-menu>
- <el-dropdown-item command="handleEditDevice">手动添加</el-dropdown-item>
- <el-dropdown-item command="handleBatchImport">批量导入</el-dropdown-item>
- </el-dropdown-menu>
- </template>
- </el-dropdown>
- <!-- <el-dropdown @command="handleCommand1">
- <el-button size="default" type="primary">
- 分配设备
- <el-icon class="el-icon--right"><arrow-down /></el-icon>
- </el-button>
- <template #dropdown>
- <el-dropdown-menu>
- <el-dropdown-item command="handleSelectAllot">选择分配</el-dropdown-item>
- <el-dropdown-item command="handleImportAllot">导入分配</el-dropdown-item>
- </el-dropdown-menu>
- </template>
- </el-dropdown> -->
- <!-- <el-button
- size="default"
- type="primary"
-
- @click="recycleDevice"
- style="margin-left: 10px"
- >回收设备</el-button
- > -->
- </div>
- <div>
- <el-radio-group class="float-right ml-10" plain v-model="showType">
- <el-radio-button label="card"
- ><el-icon><Menu /></el-icon
- ></el-radio-button>
- <el-radio-button label="list"
- ><el-icon><Fold /></el-icon
- ></el-radio-button>
- </el-radio-group>
- <right-toolbar v-model:showSearch="showSearch" @query-table="getList" />
- </div>
- </div>
- <el-row :gutter="30" v-loading="loading" style="flex-wrap: wrap">
- <el-col
- :xs="24"
- :sm="12"
- :md="8"
- :lg="6"
- :xl="6"
- v-for="(item, index) in deviceList"
- :key="index"
- style="margin-bottom: 30px; text-align: center"
- >
- <el-card :body-style="{ padding: '20px' }" shadow="hover" class="card-item" style="border: 0;">
- <el-row :gutter="10" justify="space-between">
- <el-col :span="18" style="text-align: left">
- <el-link
- type=""
- :underline="false"
- style="font-weight: bold; font-size: 16px; line-height: 32px"
- >
- <el-tooltip class="item" effect="dark" content="分享的设备" placement="top-start">
- <Icon
- icon="svg-icon:share"
- style="font-size: 20px; vertical-align: -6px"
- v-if="item.isOwner != 1"
- />
- </el-tooltip>
- <Icon icon="svg-icon:device" v-if="item.isOwner == 1" />
- <span class="card-item__title" @click="handleDeviceDetail(item)">{{
- item.deviceName
- }}</span>
- <dict-tag :type="DICT_TYPE.VIDEO_DEVICE_STATUS" :value="item.status" />
- </el-link>
- </el-col>
- <el-col :span="3" style="font-size: 20px; padding-top: 5px; cursor: pointer">
- <el-image
- style="width: 20px; height: 20px"
- :src="qrcode"
- :fit="fit"
- @click="openSummaryDialog(item)"
- />
- </el-col>
- <el-col :span="2">
- <div style="font-size: 28px; color: #ccc;">
- <Icon icon="svg-icon:wifi_4" style="font-size: 26px;" v-if="item.status == 3 && item.rssi >= '-55'" />
- <Icon
- style="font-size: 26px;"
- icon="svg-icon:wifi_3"
- v-else-if="item.status == 3 && item.rssi >= '-70' && item.rssi < '-55'"
- />
- <Icon
- style="font-size: 26px;"
- icon="svg-icon:wifi_2"
- v-else-if="item.status == 3 && item.rssi >= '-85' && item.rssi < '-70'"
- />
- <Icon
- style="font-size: 26px;"
- icon="svg-icon:wifi_1"
- v-else-if="item.status == 3 && item.rssi >= '-100' && item.rssi < '-85'"
- />
- <Icon icon="svg-icon:wifi_0" v-else style="font-size: 26px;" />
- </div>
- </el-col>
- </el-row>
- <el-row :gutter="10">
- <el-col :span="17">
- <div style="text-align: left; line-height: 40px; white-space: nowrap">
- <el-tag v-if="item.protocolCode" class="mr-5" type="primary" size="default">
- {{ item.protocolCode }}
- </el-tag>
- <el-tag v-if="item.transport" class="mr-5" type="primary" size="default">
- {{ item.transport }}
- </el-tag>
- </div>
- <el-descriptions :column="1" size="small" style="white-space: nowrap">
- <el-descriptions-item label="编号">
- <span class="font-primary">{{ item.serialNumber }}</span>
- </el-descriptions-item>
- <el-descriptions-item label="产品">
- {{ item.productName }}
- </el-descriptions-item>
- <el-descriptions-item label="创建时间">
- {{ parseTime(item.createTime, '{y}-{m}-{d}') }}
- </el-descriptions-item>
- <el-descriptions-item label="所在部门">
- {{ item.deptName || '无' }}
- </el-descriptions-item>
- <el-descriptions-item label="关联设备">
- {{ item.deviceCode || '无' }}
- </el-descriptions-item>
- </el-descriptions>
- </el-col>
- <el-col :span="7">
- <div style="margin-top: 10px">
- <el-image
- style="width: 80px; height: 80px; border-radius: 10px"
- lazy
- :preview-src-list="[baseUrl + item.imgUrl]"
- :src="baseUrl + item.imgUrl"
- fit="cover"
- v-if="item.imgUrl != null && item.imgUrl != ''"
- />
- <el-image
- style="width: 80px; height: 80px; border-radius: 10px"
- :preview-src-list="[gatewayImage]"
- :src="gatewayImage"
- fit="cover"
- v-else-if="item.deviceType == 2"
- />
- <el-image
- style="width: 80px; height: 80px; border-radius: 10px"
- :preview-src-list="[videoImage]"
- :src="videoImage"
- fit="cover"
- v-else-if="item.deviceType == 3"
- />
- <el-image
- style="width: 80px; height: 80px; border-radius: 10px"
- :preview-src-list="[productImage]"
- :src="productImage"
- fit="cover"
- v-else
- />
- </div>
- </el-col>
- </el-row>
- <div class="card-item__footer">
- <el-button class="delete-btn" size="small" @click="handleDelete(item)"
- >删除</el-button
- >
- <el-button class="detail-btn" size="small" @click="handleEditDevice(item, 'basic')"
- >查看详情</el-button
- >
- <el-button size="small" @click="handleRunDevice(item)">运行状态</el-button>
- </div>
- </el-card>
- </el-col>
- </el-row>
- <el-empty description="暂无数据,请添加设备" v-if="total == 0" />
- <pagination
- v-show="total > 0"
- :total="total"
- v-model:page="queryParams.pageNum"
- v-model:limit="queryParams.pageSize"
- :page-sizes="[12, 24, 36, 60]"
- @pagination="getList"
- />
- </el-card>
- <!-- 二维码 -->
- <el-dialog v-model="openSummary" width="300px" append-to-body>
- <div
- style="
- border: 1px solid #ccc;
- width: 220px;
- text-align: center;
- margin: 0 auto;
- margin-top: -15px;
- "
- >
- <Vue3NextQrcode :text="qrText" :size="200" />
- <div style="padding-bottom: 10px">设备二维码</div>
- </div>
- </el-dialog>
- <!-- 批量导入设备 -->
- <batchImport ref="batchImportRef" @save="saveDialog" />
- <!-- 导入分配 -->
- <!-- <allotImport ref="allotImportRef" @save="saveAllotDialog" /> -->
- <!-- 导入记录 -->
- <!-- <importRecord ref="importRecordRef" /> -->
- <!-- 设备回收记录 -->
- <!-- <recycleRecord ref="recycleRecordRef" /> -->
- <!-- 设备分配记录 -->
- <!-- <allotRecord ref="allotRecordRef" /> -->
- </div>
- </template>
- <script setup>
- import { ref, reactive, onMounted, onActivated, computed } from 'vue'
- import { useRouter, useRoute } from 'vue-router'
- import { useStore } from 'vuex'
- import { ElMessage, ElMessageBox } from 'element-plus'
- import { useUserStoreWithOut } from '@/store/modules/user'
- import {
- Search,
- Refresh,
- InfoFilled,
- Plus,
- Delete,
- View,
- ArrowDown,
- Menu,
- Fold
- } from '@element-plus/icons-vue'
- import { getCurrentInstance } from 'vue'
- import { listDeviceShort, delDevice } from '@/api/pms/video/device'
- import { delSipDeviceBySipId } from '@/api/pms/video/sipdevice'
- import Treeselect from '@riophae/vue-treeselect'
- import '@riophae/vue-treeselect/dist/vue-treeselect.css'
- import { parseTime } from '@/utils/dateUtil'
- import { Vue3NextQrcode } from 'vue3-next-qrcode'
- import 'vue3-next-qrcode/es/style.css'
- import batchImport from './batch-import-dialog.vue'
- // import allotImport from './allot-import-dialog.vue'
- // import importRecord from './import-record.vue'
- // import recycleRecord from './recycle-record.vue'
- // import allotRecord from './allot-record.vue'
- // 图片资源
- import gatewayImage from '@/assets/imgs/gateway.svg'
- import videoImage from '@/assets/imgs/video.svg'
- import productImage from '@/assets/imgs/product.svg'
- import qrcode from '@/assets/imgs/qrcode.png'
- import SvgIcon from '@/components/SvgIcon/index.vue'
- import { DICT_TYPE, getDictLabel, getStrDictOptions } from '@/utils/dict'
- import DeptTree from '@/views/system/user/DeptTree.vue'
- import { defaultProps, handleTree } from '@/utils/tree'
- import * as DeptApi from '@/api/system/dept'
- const { proxy } = getCurrentInstance()
- // Vue Router 和 Store
- const router = useRouter()
- const route = useRoute()
- const store = useStore()
- // Refs
- const queryFormRef = ref()
- const batchImportRef = ref()
- const allotImportRef = ref()
- const importRecordRef = ref()
- const recycleRecordRef = ref()
- const allotRecordRef = ref()
- // 数据响应式变量
- const qrText = ref('yanfan')
- const openSummary = ref(false)
- const showSearch = ref(true)
- const showType = ref('card')
- const loading = ref(true)
- const total = ref(0)
- const deviceList = ref([])
- const myGroupList = ref([])
- const uniqueId = ref('')
- // 基础URL
- const baseUrl = import.meta.env.VITE_BASE_URL
- // 查询参数
- const queryParams = reactive({
- pageNum: 1,
- pageSize: 12,
- showChild: true,
- deviceName: null,
- productId: null,
- groupId: null,
- productName: null,
- userId: null,
- userName: null,
- tenantId: null,
- tenantName: null,
- serialNumber: null,
- status: null,
- networkAddress: null,
- activeTime: null,
- deptId:null
- })
- // 表单参数
- const form = reactive({
- productId: 0,
- status: 1,
- locationWay: 1,
- firmwareVersion: 1.0,
- serialNumber: '',
- deviceType: 1,
- isSimulate: 0,
- deviceId: 0
- })
- // 批量导入参数
- const isSubDev = ref(false)
- const deptList = ref([])
- // 生命周期钩子
- onMounted(async() => {
- const time = route.query.t
- if (time != null && time != uniqueId.value) {
- uniqueId.value = time
- // 页码筛选
- let pageNum = route.query.pageNum
- if (pageNum != null) {
- queryParams.pageNum = Number(pageNum)
- }
- // 产品筛选
- let productId = route.query.productId
- if (productId != null) {
- queryParams.productId = Number(productId)
- queryParams.groupId = null
- queryParams.serialNumber = null
- }
- // 分组筛选
- let groupId = route.query.groupId
- if (groupId != null) {
- queryParams.groupId = Number(groupId)
- queryParams.productId = null
- queryParams.serialNumber = null
- }
- // 设备编号筛选
- let sn = route.query.sn
- if (sn != null) {
- queryParams.serialNumber = sn
- queryParams.productId = null
- queryParams.groupId = null
- }
- }
- getList()
- deptList.value = handleTree(await DeptApi.getSimpleDeptList())
- // 以后会用,暂时注释掉
- // connectMqtt()
- })
- onActivated(() => {
- const time = route.query.t
- if (time != null && time != uniqueId.value) {
- uniqueId.value = time
- // 页码筛选
- let pageNum = route.query.pageNum
- if (pageNum != null) {
- queryParams.pageNum = Number(pageNum)
- }
- // 产品筛选
- let productId = route.query.productId
- if (productId != null) {
- queryParams.productId = Number(productId)
- queryParams.groupId = null
- queryParams.serialNumber = null
- }
- // 分组筛选
- let groupId = route.query.groupId
- if (groupId != null) {
- queryParams.groupId = Number(groupId)
- queryParams.productId = null
- queryParams.serialNumber = null
- }
- // 设备编号筛选
- let sn = route.query.sn
- if (sn != null) {
- queryParams.serialNumber = sn
- queryParams.productId = null
- queryParams.groupId = null
- }
- getList()
- }
- })
- // 方法定义
- /* 连接Mqtt消息服务器 */
- async function connectMqtt() {
- if (proxy.$mqttTool.client == null) {
- await proxy.$mqttTool.connect()
- }
- mqttCallback()
- getList()
- }
- /* Mqtt回调处理 */
- function mqttCallback() {
- proxy.$mqttTool.client.on('message', (topic, message, buffer) => {
- let topics = topic.split('/')
- let productId = topics[1]
- let deviceNum = topics[2]
- message = JSON.parse(message.toString())
- if (!message) {
- return
- }
- if (topics[3] == 'status') {
- // 更新列表中设备的状态
- for (let i = 0; i < this.deviceList.length; i++) {
- if (this.deviceList[i].serialNumber == deviceNum) {
- this.deviceList[i].status = message.status
- this.deviceList[i].isShadow = message.isShadow
- this.deviceList[i].rssi = message.rssi
- return
- }
- }
- }
- })
- }
- // 新增设备更多操作触发
- function handleCommand(command) {
- switch (command) {
- case 'handleEditDevice':
- handleEditDevice(0)
- break
- case 'handleBatchImport':
- handleBatchImport()
- break
- default:
- break
- }
- }
- //批量导入设备
- function handleBatchImport() {
- if (batchImportRef.value) {
- batchImportRef.value.showDialog()
- batchImportRef.value.importForm.productId = null
- }
- }
- //导入分配设备
- function handleImportAllot() {
- if (allotImportRef.value) {
- allotImportRef.value.upload.importAllotDialog = true
- allotImportRef.value.allotForm.productId = null
- allotImportRef.value.allotForm.deptId = null
- }
- }
- // dialog 保存响应
- function saveDialog() {
- getList()
- }
- // dialog 保存响应
- function saveAllotDialog() {
- getList()
- }
- // 分配设备更多操作触发
- function handleCommand1(command) {
- switch (command) {
- case 'handleSelectAllot':
- handleSelectAllot()
- break
- case 'handleImportAllot':
- handleImportAllot()
- break
- default:
- break
- }
- }
- //跳转选择分配设备页面
- function handleSelectAllot() {
- router.push({
- path: '/iotdev/iot/device-select-allot'
- })
- }
- //跳转回收设备页面
- function recycleDevice() {
- router.push({
- path: '/iotdev/iot/device-recycle'
- })
- }
- //更多操作
- function handleCommandMore(command) {
- switch (command) {
- case 'importRecord':
- handleImportRecord()
- break
- case 'exportDevice':
- handleexportDevice()
- break
- case 'recycleRecord':
- handleRecycleRecord()
- break
- case 'allotRecord':
- handleAllotRecord()
- break
- default:
- break
- }
- }
- //导入记录
- function handleImportRecord() {
- if (importRecordRef.value) {
- importRecordRef.value.open = true
- }
- }
- //设备回收记录
- function handleRecycleRecord() {
- if (recycleRecordRef.value) {
- recycleRecordRef.value.open = true
- }
- }
- //设备分配记录
- function handleAllotRecord() {
- if (allotRecordRef.value) {
- allotRecordRef.value.open = true
- }
- }
- function openSummaryDialog(row) {
- let json = {
- type: 1, // 1=扫码关联设备
- deviceNumber: row.serialNumber,
- productId: row.productId,
- productName: row.productName
- }
- qrText.value = JSON.stringify(json)
- openSummary.value = true
- }
- /* 订阅消息 */
- function mqttSubscribe(list) {
- // 订阅当前页面设备状态和实时监测
- let topics = []
- for (let i = 0; i < list.length; i++) {
- let topicStatus = '/' + '+' + '/' + list[i].serialNumber + '/status/post'
- topics.push(topicStatus)
- }
- proxy.$mqttTool.subscribe(topics)
- }
- /** 查询设备分组列表 */
- const userStore = useUserStoreWithOut()
- /** 查询所有简短设备列表 */
- function getList() {
- loading.value = true
- queryParams.params = {}
- listDeviceShort(queryParams)
- .then((response) => {
- deviceList.value = response
- total.value = response.length
- // 订阅消息
- // if (deviceList.value && deviceList.value.length > 0) {
- // mqttSubscribe(deviceList.value)
- // }
- })
- .catch((e) => {
- console.error(e)
- })
- .finally(() => {
- loading.value = false
- })
- }
- /** 搜索按钮操作 */
- function handleQuery() {
- queryParams.pageNum = 1
- getList()
- }
- /** 重置按钮操作 */
- function resetQuery() {
- queryParams.productId = null
- queryParams.groupId = null
- queryParams.serialNumber = null
- if (queryFormRef.value) {
- queryFormRef.value.resetFields()
- }
- handleQuery()
- }
- // 点击名称查看
- function handleDeviceDetail(item) {
- handleEditDevice(item)
- }
- /** 修改按钮操作 */
- function handleEditDevice(row, activeName) {
- let deviceId = 0
- let isSubDevValue = 0
- if (row != 0) {
- deviceId = row.deviceId || 0 // 这里需要根据实际情况调整
- isSubDevValue = row.subDeviceCount > 0 ? 1 : 0
- }
- router.push({
- name: 'VideoCenterDeviceEdit',
- query: {
- deviceId: deviceId,
- isSubDev: isSubDevValue,
- pageNum: queryParams.pageNum,
- activeName: activeName
- }
- })
- }
- /** 运行状态按钮操作 */
- function handleRunDevice(row) {
- let deviceId = 0
- let isSubDevValue = 0
- if (row != 0) {
- deviceId = row.deviceId || 0 // 这里需要根据实际情况调整
- isSubDevValue = row.subDeviceCount > 0 ? 1 : 0
- }
- if (row.deviceType === 3) {
- router.push({
- path: '/videocenter/device/device-edit',
- query: {
- deviceId: deviceId,
- isSubDev: isSubDevValue,
- pageNum: queryParams.pageNum,
- activeName: 'sipChannel'
- }
- })
- } else {
- router.push({
- path: '/videocenter/device/device-edit',
- query: {
- deviceId: deviceId,
- isSubDev: isSubDevValue,
- pageNum: queryParams.pageNum,
- activeName: 'runningStatus'
- }
- })
- }
- }
- /** 删除按钮操作 */
- function handleDelete(row) {
- const deviceIds = row.deviceId || 0 // 这里需要根据实际情况调整
- ElMessageBox.confirm('是否确认删除设备编号为"' + deviceIds + '"的数据项?', '提示', {
- confirmButtonText: '确定',
- cancelButtonText: '取消',
- type: 'warning'
- })
- .then(() => {
- if (row.deviceType === 3) {
- delSipDeviceBySipId(row.serialNumber)
- }
- return delDevice(deviceIds)
- })
- .then(() => {
- getList()
- ElMessage.success('删除成功')
- })
- .catch(() => {})
- }
- /** 未启用设备影子*/
- function shadowUnEnable(device, thingsModel) {
- // 1-未激活,2-禁用,3-在线,4-离线
- if (device.status != 3 && device.isShadow == 0) {
- return true
- }
- if (thingsModel.isReadonly) {
- return true
- }
- return false
- }
- // 获取表格图片
- function getImg(row) {
- switch (row.deviceType) {
- case 2:
- return gatewayImage
- case 3:
- return videoImage
- default:
- return productImage
- }
- }
- </script>
- <style lang="scss" scoped>
- ::v-deep(.el-upload-dragger) {
- width: 510px;
- }
- .el-dropdown-menu__item {
- font-size: 12px;
- /* 设置字体大小 */
- }
- .font-primary {
- color: #0147eb;
- }
- .device {
- --font-grey: #606266;
- --success-color: #67c23b;
- padding: 20px;
- .search-form {
- .el-form-item {
- :deep(.el-form-item__label) {
- font-weight: normal;
- color: var(--font-grey);
- }
- }
- }
- .main-card.el-card {
- margin-top: 20px;
- padding-bottom: 50px;
- border: none;
- .card-toolbar {
- display: flex;
- justify-content: space-between;
- margin-bottom: 20px;
- .el-radio-button {
- ::deep(.el-radio-button__inner) {
- background-color: #f0f2f5;
- border-color: #fff;
- }
- &.is-active {
- ::deep(.el-radio-button__orig-radio:checked + .el-radio-button__inner) {
- background-color: #0147eb;
- border-color: #0147eb;
- }
- }
- }
- }
- .is-publish {
- font-size: 12px;
- white-space: nowrap;
- color: var(--success-color);
- &:before {
- margin-right: 4px;
- display: inline-block;
- width: 4px;
- height: 4px;
- border-radius: 2px;
- vertical-align: 2px;
- background: var(--success-color);
- content: '';
- }
- }
- .el-table {
- :deep(.el-table__header th) {
- color: #9a9da3;
- border-color: #f6f8fa;
- background-color: #f5f7fa;
- }
- :deep(.el-table__body .el-table__cell) {
- color: #606266;
- padding: 8px 0;
- border-color: #f6f8fa;
- .el-button {
- border-color: transparent;
- background: transparent;
- &:hover {
- &.el-button--danger {
- color: #ff9999;
- }
- &.el-button--primary {
- color: #91a8f8;
- }
- }
- &.el-button {
- margin-left: 2px;
- }
- }
- }
- }
- .pagination-container {
- :deep(.el-pagination) {
- .el-pager li:not(.disabled).active {
- background-color: #0147eb;
- }
- }
- }
- }
- .card-item {
- height: 100%;
- border-radius: 4px;
- background-image: linear-gradient(#e9f1fc, #fefefe);
- :deep(.el-card__body) {
- display: flex;
- height: 100%;
- flex-direction: column;
- justify-content: space-between;
- }
- .card-item__title {
- vertical-align: -2px;
- margin-right: 0.5em;
- font-size: 16px;
- line-height: 32px;
- color: black;
- }
- .el-descriptions {
- :deep(.el-descriptions__body) {
- background: transparent;
- }
- }
- .card-item__footer {
- margin-top: 1em;
- display: flex;
- justify-content: center;
- padding: 0 5px;
- .el-button {
- background: #f5f7fa;
- border-color: #f5f7fa;
- &.detail-btn {
- color: #0147eb;
- }
- &.delete-btn {
- color: #ff6363;
- }
- &:hover {
- border-color: #0147eb;
- color: #0147eb;
- }
- }
- }
- }
- }
- </style>
|