Newer
Older
safe_production_front / src / views / system / bsConfig / index.vue
dutingting 5 days ago 12 KB bug修复
<!-- 大屏配置页面 -->
<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>