<!-- 大屏配置页面 --> <script lang="ts" setup name="ResourceList"> import type { Ref } from 'vue' import { getCurrentInstance, nextTick, reactive, ref } from 'vue' import { ElLoading, ElMessage, ElMessageBox } from 'element-plus' import { getDictByCode } from '@/api/system/dict' import type { dictType } from '@/global' import { pictureAdd } from '@/api/monitor/realTime' import { videoTree } from '@/api/monitor/broadcast' import importSelectSecretDialog from '@/views/monitor/deviceManage/importSelectSecretDialog.vue' import { getConfig, updateConfig } from '@/api/bs' const treeRef = ref(null) as any const data = ref([]) as any const filterText = ref('') const videoConfigCount = ref(6) // 配置的视频数量 const configData: any = ref([]) // 配置数据 const defaultProps = ref({ children: 'children', label: 'name', isDisabled: 'disabled', }) const loading = ref(false) // 表格表头 const columns = ref([ { text: '设备名称', value: 'monitorName', align: 'center' }, { text: '设备类型', value: 'deviceTypeName', align: 'center' }, { text: '所属单位', value: 'deptName', align: 'center' }, { text: '所属区域', value: 'areaName', align: 'center' }, { text: '经度', value: 'longitude', align: 'center' }, { text: '纬度', value: 'latitude', align: 'center' }, { text: '密级', value: 'secretLevelName', align: 'center', width: 100 }, { text: '设备状态', value: 'deviceStatusName', align: 'center' }, ]) function filterNode(value: any, data: { name: string | any[] }) { if (value === '' || value === null) { return true } if ('name' in data) { return data.name.includes(value) } } let treeClickCount = 0 // 用于双击事件判断 // 双击树节点 function handleNodeClick(data: any, node: any, self: any) { console.log('设备信息', data) if (data.device.deviceStatusName === '离线') { ElMessage.warning(`设备 ${data.device.monitorName} 离线, 不允许配置到数据大屏中`) return false } const now = new Date().getTime() if (now - treeClickCount < 300) { // 双击事件的判断,300毫秒内重复点击 if (data.children.length !== 0) { // 点击父亲 return } // if (configData.value.length >= 6) { // ElMessage.warning(`最大允许配置${videoConfigCount.value}个`) // return false // } const index = configData.value.findIndex((item: { cameraIndexCode: string }) => item.cameraIndexCode === data.device.cameraIndexCode) if (index === -1) { configData.value.push({ monitorName: data.device.monitorName, // 设备名称 deviceTypeName: data.device.deviceTypeName, // 设备类型 deptName: data.device.deptName, // 所属单位 areaName: data.device.areaName, // 所属区域 longitude: data.device.longitude, // 经度 latitude: data.device.latitude, // 纬度 secretLevelName: data.device.secretLevelName, // 密级 deviceStatusName: data.device.deviceStatusName, // 设备状态 cameraIndexCode: data.device.cameraIndexCode, // 设备国标号 nvrIndexCode: data.device.nvrIndexCode, }) } else { ElMessage.warning('此设备已经添加到表格中') } } treeClickCount = now } // 删除 const del = (index: number) => { configData.value.splice(index, 1) } // -------------------------------------------文件上传-------------------------------------- const uploadIndex = ref(0) const uploadRow: any = ref() const fileRef = ref() // 文件上传input const onFileChange = (event: any) => { console.log('event.target.files', event.target.files) if (event.target.files?.length !== 0) { let base64String = '' const reader = new FileReader() reader.readAsDataURL(event.target.files[0]) reader.onload = (e: any) => { base64String = e.target.result const params = { devId: uploadRow.value.cameraIndexCode, picture: base64String, } const loading = ElLoading.service({ lock: true, background: 'rgba(255, 255, 255, 0.8)', }) pictureAdd(params).then((res) => { if (res.code === 200) { configData.value[uploadIndex.value].picture = `${window.localStorage.getItem('baseURL')}/picture/download/${res.data}?token=${window.localStorage.getItem('token')}` configData.value[uploadIndex.value].url = res.data console.log('图片地址', configData.value[uploadIndex.value].picture) event.target.value = null // 重置当前验证 ElMessage.success('文件上传成功') loading.close() } else { ElMessage.error(res.message) loading.close() } }) } } } const importSelectSecretDialogRef = ref() const upload = (row: any, index: number) => { uploadRow.value = row uploadIndex.value = index importSelectSecretDialogRef.value.initDialog() } const confirmSecret = () => { fileRef.value.click() } // ----------------------------------------------------------------------------------------------------- // 获取列表 const fetchData = () => { getConfig().then((res) => { if (res.data !== 'false' && res.data !== '') { configData.value = JSON.parse(res.data) configData.value = configData.value.map((item: any) => { return { ...item, picture: `${window.localStorage.getItem('baseURL')}/picture/download/${item.url}?token=${window.localStorage.getItem('token')}`, } }) console.log('pppppp', configData.value) } else { configData.value = [] } }) } // 保存配置 const saveConfig = () => { // if (configData.value.length !== 4) { // ElMessage.warning('请配置4条数据') // return false // } ElMessageBox.confirm( '确定要保存配置吗?', '确认保存', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning', }, ).then(() => { const params = JSON.stringify(configData.value) updateConfig({ data: params }).then(() => { ElMessage.success('配置成功') fetchData() }) }) } const unwatch = watch(filterText, (newVal) => { treeRef.value.filter(newVal) }) // -------------------------------------------字典------------------------------------------ // 获取字典值 // async function getDict() { // // 是否加急 // const res = await getDictByCode('approvalLogType') // videoConfigCount.value = res.data[0].value // } // ---------------------------------------------------------------------------------------- onBeforeUnmount(() => { unwatch() }) onMounted(() => { // getDict() fetchData() // 获取树 videoTree().then((response) => { if (response.code === 200) { data.value = response.data } }) }) </script> <template> <app-container style="height: calc(100vh - 110px)"> <input v-show="false" ref="fileRef" type="file" @change="onFileChange"> <div style="display: flex;height: 100%"> <el-card class="left" :body-style="{ padding: '10px' }"> <el-input v-model="filterText" placeholder="设备名称过滤" style="margin-bottom: 10px;" clearable /> <el-tree ref="treeRef" class="filter-tree" style="width: 100%;height: 100%" :data="data" node-key="id" :filter-node-method="filterNode" :default-expand-all="true" :props="defaultProps" highlight-current @node-click="handleNodeClick" > <template #default="{ node, data }"> <span style="display: flex;align-items: center;"> <el-tooltip class="box-item" effect="dark" :content="node.label" placement="right" > <template #content> <span>{{ node.label }}</span> <span v-if="data && data.device && data.device.deviceTypeName">({{ data.device.deviceTypeName }})</span> </template> <span v-if="data && data.device && data.device.deviceTypeName" :style="{ 'color': data.device.deviceStatusName === '在线' ? '#0e932e' : '#606266', 'font-weight': data.device.deviceStatusName === '在线' ? 600 : 500 }">{{ node.label }}</span> <span v-else>{{ node.label }}</span> </el-tooltip> <el-icon v-if="data && data.device && data.device.deviceType === '0'" style="margin-left: 5px"> <svg-icon name="icon-qiang" :color="data.device.deviceStatusName === '在线' ? '#0e932e' : '#979797'"/> </el-icon> <el-icon v-if="data && data.device && (data.device.deviceType === '1' || data.device.deviceType === '2')" style="margin-left: 5px;"> <svg-icon name="icon-ball" :color="data.device.deviceStatusName === '在线' ? '#0e932e' : '#979797'" /> </el-icon> <el-icon v-if="data && data.device && data.device.deviceType === '3'" style="margin-left: 5px;"> <svg-icon name="icon-ball" :color="data.device.deviceStatusName === '在线' ? '#0e932e' : '#979797'" /> </el-icon> <el-icon v-if="data && data.device && data.device.deviceType === '4'" style="margin-left: 5px;"> <svg-icon name="icon-ytqiang" :color="data.device.deviceStatusName === '在线' ? '#0e932e' : '#979797'" /> </el-icon> <!-- <span v-if="data.device.deviceTypeName">{{ node.label.slice(node.label.indexOf('(')) }}</span> --> </span> </template> </el-tree> </el-card> <div class="right"> <div style="width: 100%;display: flex;justify-content: space-between;"> <!-- <div><span style="font-size: 13px;">最大配置数量:</span><span style="font-weight: 600;color: red;font-size: 20px;">{{videoConfigCount}}</span></div> --> <div><span style="font-size: 13px;">当前配置数量:</span><span style="font-weight: 600;color: red;font-size: 20px;">{{configData.length}}</span></div> <el-button type="primary" @click="saveConfig"> 保存配置 </el-button> </div> <table-container> <normal-table :list-loading="loading" :columns="columns" :data="configData" :pagination="false" :border="false" > <!-- 序号 --> <template #preColumns> <el-table-column label="序号" width="55" align="center"> <template #default="scope"> {{ scope.$index + 1 }} </template> </el-table-column> </template> <template #columns> <el-table-column label="图片" width="120" align="center"> <template #default="scope"> <el-image v-if="scope.row.picture" :src="scope.row.picture" :preview-src-list="[scope.row.picture]" fit="cover" :preview-teleported="true" /> <el-button type="primary" size="small" class="table-text-button" @click="upload(scope.row, scope.$index)"> {{ scope.row.picture ? '更换' : '上传' }} </el-button> </template> </el-table-column> <el-table-column label="操作" width="120" align="center"> <template #default="scope"> <el-button type="danger" link size="small" class="table-text-button" @click="del(scope.$index)"> 删除 </el-button> </template> </el-table-column> </template> </normal-table> </table-container> </div> </div> <import-select-secret-dialog ref="importSelectSecretDialogRef" title="选择导入图片的密级" typeTitle="图片" @confirm-secret="confirmSecret" /> </app-container> </template> <style lang="scss" scoped> .left { box-sizing: border-box; width: 380px; height: 100%; overflow-y: scroll; overflow-x: scroll; } .right { flex: 1; height: 100%; background-color: #fff; border-radius: 4px; margin: 0px 10px; padding: 10px; } </style> <style lang="scss"> .el-tree-node__content { padding-left: 0 !important; } .el-tree { width: 100%; } .el-tree > .el-tree-node { display: inline-block; min-width: 100%; } </style>