Browse Source

阀位管理系统

codeMan 7 months ago
parent
commit
448780fba3

BIN
src/assets/controlPanel/icon/bgheader3.png


+ 13 - 2
src/operation/moduleNormal/equipmentMag/modules/Add.vue

@@ -150,6 +150,16 @@
             <a-input v-model:value="form.address" placeholder="请输入地址"></a-input>
           </a-form-item>
         </a-col>
+        <a-col :span="24">
+          <a-form-item  label="所属系统" name="sys_msgprotocolid" :rules="[{required:true,message:'请选择所属系统'}]">
+            <a-select
+              v-model:value="form.systemname"
+              placeholder="请选择所属系统"
+            >
+              <a-select-option v-for="item in systemList" :key="item.remarks" :value="item.value">{{ item.remarks }}</a-select-option>
+            </a-select>
+          </a-form-item>
+        </a-col>
         <!-- <a-col :span="24">
           <a-form-item  label="是否启用" name="isused">
             <a-checkbox v-model:checked="form.isused"></a-checkbox>
@@ -371,12 +381,13 @@ let createDeep = (array) => {
 }
 
 
+let systemList = ref([])
 onMounted(async () => {
   let res = await base.optiontypeselect('msgprotocol')
   msgprotocolList.value = res.data
-  console.log(msgprotocolList.value,'消息协议');
+  let res2 = await base.optiontypeselect('systemname')
+  systemList.value = res2.data
   province.value = await base.ProvincesData()
-  console.log(province.value);
 })
 
 </script>

+ 13 - 1
src/operation/moduleNormal/equipmentMag/modules/Edit.vue

@@ -152,6 +152,16 @@
             <a-input v-model:value="form.address" placeholder="请输入地址"></a-input>
           </a-form-item>
         </a-col>
+        <a-col :span="24">
+          <a-form-item  label="所属系统" name="sys_msgprotocolid" :rules="[{required:true,message:'请选择所属系统'}]">
+            <a-select
+              v-model:value="form.systemname"
+              placeholder="请选择所属系统"
+            >
+              <a-select-option v-for="item in systemList" :key="item.remarks" :value="item.value">{{ item.remarks }}</a-select-option>
+            </a-select>
+          </a-form-item>
+        </a-col>
         <!-- <a-col :span="24">
           <a-form-item  label="是否启用" name="isused">
             <a-checkbox v-model:checked="form.isused"></a-checkbox>
@@ -369,10 +379,12 @@ let createDeep = (array) => {
 }
 
 
+let systemList = ref([])
 onMounted(async () => {
   let res = await base.optiontypeselect('msgprotocol')
   msgprotocolList.value = res.data
-  console.log(msgprotocolList.value,'消息协议');
+  let res2 = await base.optiontypeselect('systemname')
+  systemList.value = res2.data
   province.value = await base.ProvincesData()
 })
 

+ 1018 - 0
src/operation/moduleNormal/positionControl/index.vue

@@ -0,0 +1,1018 @@
+<template>
+  <div class="control">
+    <div class="bg_header">
+      <img src="@/assets/controlPanel/icon/bgheader3.png" alt="">
+      <div class="header-handle">
+        <weather/>
+        <div>
+          <a-dropdown class="dropdown-link" overlayClassName="site-custom__classname">
+            <a class="ant-dropdown-link" @click.prevent>
+              <div class="siteinfo1">
+                <span style="margin-right: 25rem;"><EnvironmentOutlined />{{nowAccount.sitename}}</span>
+                <span style="margin-right: 10rem;">{{ nowAccount.name }}</span>
+                <DownOutlined />
+              </div>
+            </a>
+            <template #overlay>
+              <a-menu>
+                <a-menu-item v-for="item in accountList" :key="item.index">
+                  <a @click="accountItemClick(item,false)">{{item.sitename + '-' + item.name}}</a>
+                </a-menu-item>
+                <a-menu-divider />
+                <a-menu-item>
+                  <LogoutOutlined />
+                  <a class="color-red" @click="loginOut">&nbsp;退出登录</a>
+                </a-menu-item>
+              </a-menu>
+            </template>
+          </a-dropdown>
+          <a-button type="primary" size="small" @click="router.push('/controlPanel')" style="position: absolute;right: 20rem;bottom:0;">退出</a-button>
+        </div>
+        
+      </div>
+    </div>
+    <div class="control_content">
+      <div class="control_content-left">
+        <ContentBox>
+          <div class="header">
+            <span>告警记录</span>
+            <a-button type="primary" size="small" @click="goPage('/warningHistory')">进入</a-button>
+          </div>
+          <div class="history-statistice">
+            <div>
+              <div class="history-item">
+                <span class="normal-title">今日告警量</span>
+                <span>{{ data.dataAll.today_total }}</span>
+              </div>
+              <div class="history-item">
+                <span class="normal-title">未处理</span>
+                <span>{{ data.dataAll.today_undeal }}</span>
+              </div>
+              <div class="history-item">
+                <span class="normal-title">已处理</span>
+                <span>{{ data.dataAll.today_deal }}</span>
+              </div>
+            </div>
+          </div>
+          <div class="history-wrapper" v-load-directive="warningLoad">
+            <div :class="[{'move':warningMove},{'history-list':true}]" @mouseenter="warningClose" @mouseleave="warningScrollUp" v-if="data.warningHistory.length">
+              <div class="history-item" v-for="(item,index) in data.warningHistory" :key="index">
+                <a-tooltip>
+                  <template #title>
+                    <span>{{ item.devicename }}</span>
+                  </template>
+                  <span>{{ item.devicename }}</span>
+                </a-tooltip>
+                <a-tooltip>
+                  <template #title>
+                    <span>{{ item.eventname }}</span>
+                  </template>
+                    <span>{{ item.eventname }}</span>
+                </a-tooltip>
+                <span :style="{color:baseSet.styleObj(eventlevelList.filter(v => v.value == item.lasteventlevel)[0] ? eventlevelList.filter(v => v.value == item.lasteventlevel)[0].remarks : '').color}">{{ eventlevelList.filter(v => v.value == item.lasteventlevel)[0] ? eventlevelList.filter(v => v.value == item.lasteventlevel)[0].remarks : '' }}</span>
+                <span>{{ item.lasteventtime }}</span>
+              </div>
+            </div>
+            <a-empty :image="simpleImage" v-else>
+              <template #description>
+                <span style="color:#ffffff">暂无数据</span>
+              </template>
+            </a-empty>
+          </div>
+        </ContentBox>
+        <ContentBox>
+          <div class="header">
+            <span>本周告警统计</span>
+            <a-button type="primary" size="small" @click="goPage('/warningControl')">进入</a-button>
+          </div>
+          <div class="history-statistice">
+            <div>
+              <div class="history-item">
+                <span class="normal-title">本周告警量</span>
+                <span>{{ data.dataAll.week_total }}</span>
+              </div>
+              <div class="history-item">
+                <span class="normal-title">紧急</span>
+                <span>{{ data.dataAll.week_emergent }}</span>
+              </div>
+              <div class="history-item">
+                <span class="normal-title">重要</span>
+                <span>{{ data.dataAll.week_important }}</span>
+              </div>
+            </div>
+          </div>
+          <div class="map" ref="map"></div>
+        </ContentBox>
+      </div>
+      <div class="control_content-center">
+        <ContentBox>
+          <div class="header">
+            <span>设备监控</span>
+            <a-button type="primary" size="small" @click="goPage('/equipmentManage')">进入</a-button>
+          </div>
+          <div class="device-statistice">
+            <div class="device-item">
+              <div class="left">
+                <span>设备数</span>
+                <span>{{ data.dataAll.device_total }}</span>
+              </div>
+              <div class="right">
+                <img src="@/assets/controlPanel/icon/设备数.png" alt="">
+              </div>
+            </div>
+            <div class="device-item">
+              <div class="left">
+                <span>在线数</span>
+                <span>{{ data.dataAll.device_online }}</span>
+              </div>
+              <div class="right">
+                <img src="@/assets/controlPanel/icon/在线数.png" alt="">
+              </div>
+            </div>
+            <div class="device-item">
+              <div class="left">
+                <span>异常数</span>
+                <span>{{ data.dataAll.device_abnormal }}</span>
+              </div>
+              <div class="right">
+                <img src="@/assets/controlPanel/icon/异常数.png" alt="">
+              </div>
+            </div>
+          </div>
+          <div class="device-wrapper" v-load-directive="deviceLoad">
+            <div class="device-list" v-if="data.deviceList.length">
+              <ContentBox v-for="(item,index) in data.deviceList" :key="index" bgColor="rgb(255,255,255,0.25)" color="#16FFF6" @click="deviceClick(item)">
+                <div style="height: 30rem;"></div>
+                <div class="siteinfo">
+                  <div class="siteinfo-wrapper">
+                    <EnvironmentOutlined />
+                    <span>{{ item.sitename || '暂无站点' }}</span>
+                  </div>
+                </div>
+                <div class="device-title" :style="[{'--bg':item.eventstatus ? 'red' : 'rgba(255, 164, 6)'},{'--icon':item.status == '离线' ? '#cccccc' : '#27AD00'}]">
+                  <i class="used"></i>
+                  <a-tooltip>
+                    <template #title>
+                      <span>{{ item.devicename }}</span>
+                    </template>
+                      <span>{{ item.devicename }}</span>
+                  </a-tooltip>
+                </div>
+                <img style="width: 100%;" :src="item.attinfos[0].url" alt="">
+                <!-- <span class="status">运行状态:<span class="text" :style="item.eventstatus ? 'color:red' : 'color:rgba(255, 164, 6)'">{{ item.eventstatus ? '告警中' : '正常' }}</span></span> -->
+              </ContentBox>
+            </div>
+            <a-empty :image="simpleImage" v-else>
+              <template #description>
+                <span style="color:#ffffff">暂无数据</span>
+              </template>
+            </a-empty>
+          </div>
+        </ContentBox>
+      </div>
+      <div class="control_content-right">
+        <ContentBox>
+          <div class="header">
+            <span>待接收的命令</span>
+          </div>
+          <div class="info-wrapper" v-load-directive="cmdLoad">
+            <div class="info-list" v-if="data.cmdList.length">
+              <template  v-for="(item) in data.cmdList">
+                  <div class="info-item"  v-for="(item2,index) in item.content" :key="index">
+                    <a-tooltip>
+                      <template #title>
+                        <span>{{ item.createdate }}</span>
+                      </template>
+                        <span>{{ item.createdate }}</span>
+                    </a-tooltip>
+                    <a-tooltip>
+                      <template #title>
+                        <span>{{ item.devicename }}</span>
+                      </template>
+                        <span>{{ item.devicename }}</span>
+                    </a-tooltip>
+                    <a-tooltip>
+                      <template #title>
+                        <span>{{ item2.title }}:{{ item2.value }}</span>
+                      </template>
+                      <span>{{ item2.title }}:{{ item2.value }}</span>
+                    </a-tooltip>
+                  </div>
+              </template>
+            </div>
+            <a-empty :image="simpleImage" v-else>
+              <template #description>
+                <span style="color:#ffffff">暂无数据</span>
+              </template>
+            </a-empty>
+          </div>
+        </ContentBox>
+        <ContentBox>
+          <div class="header">
+            <span>操作记录</span>
+          </div>
+          <div class="handle-wrapper" v-load-directive="handleLoad">
+            <div :class="[{'move':move},{'handle-list':true}]" @mouseenter="close" @mouseleave="scrollUp" v-if="data.handleHistory.length">
+                <div class="info-item"  v-for="(item,index) in data.handleHistory" :key="index">
+                  <a-tooltip>
+                    <template #title>
+                      <span>{{ item.createdate }}</span>
+                    </template>
+                      <span>{{ item.createdate }}</span>
+                  </a-tooltip>
+                  <a-tooltip>
+                    <template #title>
+                      <span>{{ item.devicename }}</span>
+                    </template>
+                      <span>{{ item.devicename }}</span>
+                  </a-tooltip>
+                  <a-tooltip>
+                    <template #title>
+                      <span>{{ item.title }}:{{ item.value }}</span>
+                    </template>
+                    <span>{{ item.title }}:{{ item.value }}</span>
+                  </a-tooltip>
+                </div>
+            </div>
+            <a-empty :image="simpleImage" v-else>
+              <template #description>
+                <span style="color:#ffffff">暂无数据</span>
+              </template>
+            </a-empty>
+          </div>
+        </ContentBox>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import weather from '@/components/weather/index.vue'
+import { Empty, Modal } from 'ant-design-vue';
+import { EnvironmentOutlined,DownOutlined,ExclamationCircleOutlined } from '@ant-design/icons-vue'
+const simpleImage = Empty.PRESENTED_IMAGE_SIMPLE;
+import baseSet from '../warningControl/baseSet.js'
+import ContentBox from '.././pressureControl/modules/Box.vue'
+import { Line } from '@antv/g2plot'
+import {ref, defineProps, defineEmits, onMounted, onUnmounted, onBeforeMount, onDeactivated, watch, createVNode} from 'vue'
+import Api from '@/api/api'
+import utils from '@/utils/utils'
+import { onBeforeRouteUpdate, useRouter } from 'vue-router'
+import { useRouteTabsStore } from '@/stores/modules/Htabs'
+import { useAuthStore } from '@/stores/modules/auth'
+import { storeToRefs } from 'pinia'
+const store = useAuthStore()
+let { system,mods,actSystem,openKeys,app,accountList,nowAccount  } = storeToRefs(store)
+
+const rotTabs = useRouteTabsStore()
+let {historyRoutes} = storeToRefs(rotTabs)
+const emit = defineEmits([])
+const router = useRouter()
+let map = ref()
+let line = ref()
+let eventlevelList = ref([])
+let loading = ref(false)
+
+let timer = ref()
+let move = ref(false)
+
+const accountItemClick = (account,bool)=>{
+  store.defaultAccount(account,()=>{
+    store.reloadPage()
+    setTimeout(() => {
+      getBaseInfo()
+      historyDataFun()
+      isRefresh.value = true
+    },1500)
+    // historyRoutes.value = []
+  })
+  if (!bool){
+    if (router.currentRoute.value.meta.isDetail) {
+      router.go(-1)
+    }
+  }else {
+    router.go(0)
+  }
+}
+
+const loginOut = ()=>{
+  Modal.confirm({
+    title: '注意',
+    icon: createVNode(ExclamationCircleOutlined),
+    content: '确定登出当前账号吗?',
+    okText: '确认',
+    cancelText: '取消',
+    onOk () {
+      historyRoutes.value = []
+      Api.loginout({})
+      router.push({path:'/'})
+    }
+  });
+}
+
+let goPage = (path) => {
+  router.push(path)
+  setTimeout(() => {
+    console.log(system.value,app.value);
+    let result
+    system.value.forEach(item => {
+      item.modules.forEach(item2 => {
+        if (item2.systemmoduleid == app.value.systemmoduleid) {
+          result = item
+        }
+      })
+    })
+    actSystem.value = result
+    store.modulesData(result)
+    openKeys.value.push(result.modules[0].apps[0].systemmoduleid)
+  })
+}
+
+let calcSizeFun = () => {
+  let baseSize = 1920
+  document.querySelector('html').style.fontSize = `${100 / baseSize}vw`
+}
+
+let scrollUp = () => {
+  timer.value = setInterval(() => {
+    let wrapper = document.querySelector('.handle-wrapper').clientHeight
+    let list = document.querySelector('.handle-list').clientHeight
+    if (list < wrapper) return
+    move.value = true
+    setTimeout(() => {
+      data.value.handleHistory.push(data.value.handleHistory.shift())
+      move.value = false
+    },500)
+  },2000)
+}
+
+let close = () => {
+  clearInterval(timer.value)
+}
+
+let warningMove = ref(false)
+let timer2 = ref()
+let warningScrollUp = () => {
+  timer2.value = setInterval(() => {
+    let wrapper = document.querySelector('.history-wrapper').clientHeight
+    let list = document.querySelector('.history-list').clientHeight
+    if (list < wrapper) return
+    warningMove.value = true
+    setTimeout(() => {
+      data.value.warningHistory.push(data.value.warningHistory.shift())
+      warningMove.value = false
+    },500)
+  },2000)
+}
+
+let warningClose = () => {
+  clearInterval(timer2.value)
+}
+
+/* 数据变量 */
+let data = ref({
+  dataAll:{},
+  warningMapData:[],
+  warningHistory:[],
+  deviceList:[],
+  handleHistory:[],
+  cmdList:[]
+})
+
+let warningParam = ref({
+  "id": 20230914133102,
+  "content": {
+      systemname:'valvesystem',
+      "pageNumber": 1,
+      "pageSize": 30
+  },
+})
+
+let deviceParam = ref({
+  "id": 20230914133302,
+  "content": {
+      systemname:'valvesystem',
+      "pageNumber": 1,
+      "pageSize": 15
+  },
+})
+
+let cmdParam = ref({
+  "id": 20230914133402,
+  "content": {
+      systemname:'valvesystem',
+      "pageNumber": 1,
+      "pageSize": 10
+  },
+})
+
+let handleParam = ref({
+  "id": 20230914133502,
+  "content": {
+      systemname:'valvesystem',
+      "pageNumber": 1,
+      "pageSize": 30
+  },
+})
+
+
+let listData = async () => {
+  let res = await Api.requested({id:20230914133002,content:{systemname:'valvesystem'}})
+  data.value.dataAll = res.data
+  console.log(data.value.dataAll,'数据统计')
+
+  let res3 = await Api.requested({id:20230914133202,content:{systemname:'valvesystem'}})
+  data.value.warningMapData = res3.data
+  data.value.warningMapData.forEach(item => item.次数 = item.count)
+  line.value.changeData(data.value.warningMapData)
+  console.log(data.value.warningMapData,'告警统计')
+}
+
+let deviceClick = (data) => {
+  router.push({
+    path:'/' + (data.dashboardpath || 'baseDevice'),
+    query: {
+      id:data.w_deviceid
+    }
+  })
+}
+
+let warningTotalPage = ref(0)
+let warningLoad = () => {
+  console.log('触发');
+  if (warningParam.value.content.pageNumber == warningTotalPage.value || loading.value == true) return
+  warningParam.value.content.pageNumber += 1
+  console.log(warningParam.value);
+  getwarningData()
+}
+
+let getwarningData = async () => {
+  loading.value = true
+  let res = await Api.requested(warningParam.value)
+  data.value.warningHistory = warningParam.value.content.pageNumber == 1 ? res.data : data.value.warningHistory.concat(res.data)
+  data.value.warningHistory.forEach(item => {
+    item.lasteventtime = item.lasteventtime.slice(5,item.lasteventtime.length)
+  })
+  warningTotalPage.value = res.pageTotal
+  setTimeout(() => {
+    loading.value = false
+  },1500)
+  console.log(data.value.warningHistory,'告警记录')
+}
+
+let DeviceTotalPage = ref(0)
+let deviceLoad = () => {
+  if (deviceParam.value.content.pageNumber == DeviceTotalPage.value || loading.value == true) return
+  deviceParam.value.content.pageNumber += 1
+  console.log(deviceParam.value);
+  getDeviceData()
+}
+
+let getDeviceData = async () => {
+  loading.value = true
+  let res = await Api.requested(deviceParam.value)
+  data.value.deviceList = deviceParam.value.content.pageNumber == 1 ? res.data : data.value.deviceList.concat(res.data)
+  DeviceTotalPage.value = res.pageTotal
+  setTimeout(() => {
+    loading.value = false
+  },1500)
+  console.log(data.value.deviceList,'设备列表')
+}
+
+
+let cmdTotalPage = ref(0)
+let cmdLoad = () => {
+  if (cmdParam.value.content.pageNumber == cmdTotalPage.value || loading.value == true) return
+  cmdParam.value.content.pageNumber += 1
+  console.log(cmdParam.value);
+  getCmdData()
+}
+
+let getCmdData = async () => {
+  loading.value = true
+  let res = await Api.requested(cmdParam.value)
+  data.value.cmdList = cmdParam.value.content.pageNumber == 1 ? res.data : data.value.cmdList.concat(res.data)
+  data.value.cmdList.forEach(item => {
+    item.createdate = item.createdate.slice(5,item.createdate.length)
+  })
+  cmdTotalPage.value = res.pageTotal
+  setTimeout(() => {
+    loading.value = false
+  },1500)
+  console.log(data.value.cmdList,'cmd列表')
+}
+
+let handleTotalPage = ref(0)
+let handleLoad = () => {
+  if (handleParam.value.content.pageNumber == handleTotalPage.value || loading.value == true) return
+  handleParam.value.content.pageNumber += 1
+  console.log(handleParam.value);
+  getHanleData()
+}
+
+let getHanleData = async () => {
+  loading.value = true
+  let res = await Api.requested(handleParam.value)
+  // data.value.handleHistory = handleParam.value.content.pageNumber == 1 ? res.data : data.value.handleHistory.concat(res.data)
+  res.data.forEach(item => {
+    item.content.forEach(item2 => {
+      data.value.handleHistory.push({
+        devicename:item.devicename,
+        createdate:item.createdate.slice(5,item.createdate.length),
+        title:item2.title,
+        value:item2.value
+      })
+    })
+  })
+  handleTotalPage.value = res.pageTotal
+  setTimeout(() => {
+    loading.value = false
+  },1000)
+  console.log(data.value.handleHistory,'操作记录')
+}
+
+let initChart = () => {
+  line.value = new Line(map.value,{
+    data:data.value.warningMapData,
+    xField: 'date',
+    yField: '次数',
+    yAxis: {
+      label: {
+        style: {
+          fill:'#ffffff'
+        },
+      },
+    },
+    xAxis: {
+      label: {
+        style:{
+          fill:'#ffffff'
+        },
+      },
+    },
+    color:['#16FFF6','rgba(255, 164, 6)'],
+    legend: {
+      position: 'bottom',
+      itemName: {
+        style: {
+          fill:'#ffffff'
+        }
+      }
+    },
+    tooltip: {
+      // formatter:(v) => {
+      //   return {name:v.paramname,value:v.value + chartData.value.find(item => item.paramname == v.paramname).unit}
+      // }
+    },
+    area: {
+      style: {
+        fillOpacity: 0.15,
+      },
+    },
+    // @TODO 后续会换一种动画方式
+    animation: {
+      appear: {
+        animation: 'path-in',
+        duration: 3000,
+      },
+    },
+  })
+  line.value.render()
+}
+
+let vLoadDirective = {
+  mounted (el,binding) {
+    let tableWarp = el
+    function handleFun (e) {
+      if (tableWarp.scrollTop + tableWarp.clientHeight >= tableWarp.scrollHeight) {
+        binding.value()
+      }
+    }
+    tableWarp.addEventListener('scroll',handleFun)
+    el.tableWarp = tableWarp
+    el.handleFun = handleFun
+  },
+  unmounted(el) {
+    el.tableWarp.removeEventListener('scroll',el.handleFun)
+  },
+}
+
+onMounted( async () => {
+  calcSizeFun()
+  initChart()
+  listData()
+  getCmdData()
+  getDeviceData()
+  getHanleData()
+  getwarningData()
+  scrollUp()
+  warningScrollUp()
+  const res = await Api.optionstype('eventlevel')
+  eventlevelList.value = res.data
+  console.log('警告等级',eventlevelList.value);
+  console.log(router.currentRoute.value.path);
+})
+
+router.beforeEach((to,from,next) => {
+  clearInterval(timer2.value)
+  clearInterval(timer.value)
+  next()
+})
+</script>
+
+
+<style>
+.site-custom__classname .ant-dropdown-menu {
+  background: rgba(5,54,178,.7) !important;
+  color: #ffffff !important;
+  padding: 0 !important;
+}
+.site-custom__classname .ant-dropdown-menu-item {
+  color: #ffffff !important;
+}
+.site-custom__classname .ant-dropdown-menu-item:hover {
+  background: rgba(5,54,178,.1) !important;
+}
+</style>
+
+<style scoped>
+.header-handle {
+  padding: 0 40rem;
+  transform: translateY(-20rem);
+  display: flex;
+  justify-content: space-between;
+}
+.weather-panel {
+  font-size: 14rem;
+  font-weight: bold;
+}
+.ant-btn-primary {
+  background:rgb(20, 49, 125) !important;
+  border-color:rgb(20, 49, 125) !important;
+}
+/deep/.weather-panel .white {
+  display: none;
+}
+/deep/.weather-panel span:nth-child(2) {
+  margin-right: 15rem;
+}
+/deep/.weather-panel span:nth-child(3) {
+  margin-right: 3rem;
+}
+/deep/.weather-panel span:nth-child(4) {
+}
+/deep/.weather-panel span:last-child {
+}
+.siteinfo1 {
+  color: #ffffff !important;
+  font-size: 14rem;
+  font-weight: bold;
+  z-index: 999999;
+  margin-right: 40rem;
+}
+.normal-title {
+  font-size: 16rem;
+  color: #ffffff;
+}
+.header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  font-size: 14rem;
+  font-weight: bold;
+  margin-bottom: 20rem;
+}
+*{
+  box-sizing: border-box;
+}
+.control {
+  width: 100%;
+  height: 100vh;
+  background: #02004D;
+  color: #ffffff;
+  --color1:#16FFF6;
+  --color2:rgba(255, 164, 6);
+  overflow: hidden;
+}
+.control .bg_header {
+  position: relative;
+}
+.control .bg_header img {
+  width: 100%;
+}
+
+.control .control_content {
+  width: 100%;
+  height: calc(100vh - 110rem);
+  margin-top: 10rem;
+  padding: 0 10rem 10rem 10rem;
+  display: flex;
+}
+.control .control_content .control_content-left {
+  flex: 1;
+  height: 100%;
+  display: flex;
+  flex-direction: column;
+  overflow: hidden;
+}
+.control .control_content .control_content-left .content_box {
+  height: 50%;
+}
+.control .control_content .control_content-left .content_box:first-child {
+  margin-bottom: 15rem;
+}
+.control .control_content .control_content-left .history-statistice {
+  display: flex;
+}
+.control .control_content .control_content-left .history-statistice > div {
+  margin: 0 auto;
+  display: flex;
+}
+.control .control_content .control_content-left .history-statistice .history-item {
+  display: flex;
+  flex-direction: column;
+  text-align: center;
+  margin-right: 20rem;
+}
+
+.control .control_content .control_content-left .history-statistice .history-item span:last-child {
+  color: var(--color2);  
+  font-size: 16rem;
+  font-weight: bold;
+}
+.control .control_content .control_content-left .history-wrapper {
+  height: calc(100% - 110rem);
+  overflow-y: scroll;
+  margin-top: 15rem;
+  padding-bottom: 15rem;
+}
+::-webkit-scrollbar {
+  display: none;
+}
+.control .control_content .control_content-left .history-wrapper .history-item {
+  display: flex;
+  justify-content: space-between;
+  margin-bottom: 10rem;
+  cursor: pointer;
+}
+.control .control_content .control_content-left .history-wrapper .history-item:last-child {
+  margin: 0;
+}
+.control .control_content .control_content-left .history-wrapper .history-item:hover {
+  background: rgba(255, 255, 255, 0.4);
+}
+
+.control .control_content .control_content-left .history-wrapper .history-item span {
+  white-space: nowrap;
+  overflow: hidden;
+  text-overflow: ellipsis;
+}
+
+.control .control_content .control_content-left .history-wrapper .history-item span:nth-child(1) {
+  flex: 1;
+}
+.control .control_content .control_content-left .history-wrapper .history-item span:nth-child(2) {
+  flex: 1;
+}
+.control .control_content .control_content-left .history-wrapper .history-item span:nth-child(3) {
+  flex: 0.5;
+}
+.control .control_content .control_content-left .history-wrapper .history-item span:nth-child(4) {
+  flex: 1;
+}
+.control .control_content .control_content-left .map {
+  height: calc(100% - 120rem);
+}
+.control .control_content .control_content-center {
+  flex: 1.5;
+  height: 100%;
+  min-width: 565rem;
+}
+.control .control_content .control_content-center .device-statistice {
+  display: flex;
+  justify-content: space-between;
+  margin: 15rem;
+}
+.control .control_content .control_content-center .device-statistice .device-item{
+  display: flex;
+  flex: 1;
+  justify-content: space-between;
+  border: 1rem solid var(--color1);
+  margin-right: 20rem;
+  padding: 10rem 20rem;
+  color: var(--color1);
+}
+.siteinfo {
+  position: absolute;
+  left: 0;
+  top: 0;
+  width: 100%;
+}
+.siteinfo .siteinfo-wrapper {
+  display: flex;
+  align-items: center;
+  align-self: flex-start;
+  width: 100%;
+  background: #40a9ff;
+}
+.siteinfo span {
+  margin-left: 10px;
+  white-space: nowrap;
+  text-overflow: ellipsis;
+  overflow: hidden;
+  font-size: 14rem;
+}
+.control .control_content .control_content-center .device-statistice .device-item:last-child {
+  margin: 0;
+}
+.control .control_content .control_content-center .device-statistice .device-item .left{
+  display: flex;
+  justify-content: space-between;
+  flex-direction: column;
+}
+.control .control_content .control_content-center .device-statistice .device-item .left span:last-child {
+  color: var(--color2);
+  font-size: 16rem;
+  font-weight: bold;
+}
+.control .control_content .control_content-center .device-statistice .device-item .right{
+  width:50rem;
+  height:50rem;
+  display: flex;
+  align-items: center;
+}.control .control_content .control_content-center .device-statistice .device-item .right img {
+  width: 100%;
+  margin-bottom: 0 !important;
+}
+.control .control_content .control_content-center .device-wrapper {
+  overflow-y: scroll;
+  height: calc(100% - 180rem);
+  margin-top: 40rem;
+}
+.control .control_content .control_content-center .device-wrapper .device-list {
+  display: flex;
+  flex-wrap: wrap;
+}
+.control .control_content .control_content-center .device-wrapper .device-list .used{
+  display: inline-block;
+  width: 10rem;
+  height: 10rem;
+  border-radius: 10rem;
+  background: var(--icon);
+  margin-right: 10rem;
+}
+.control .control_content .control_content-center .device-wrapper .device-list .device-title {
+  display: flex;
+  align-items: center;
+  height: 44rem;
+  font-size: 14rem;
+}
+.control .control_content .control_content-center .device-wrapper .device-list .device-title,img,.status {
+  margin-bottom: 10rem;
+  font-size: 14rem;
+}
+.control .control_content .control_content-center .device-wrapper .device-list .device-title span {
+  display: inline-block;
+  width: 140rem;
+  text-overflow: ellipsis;
+  overflow: hidden;
+  display: -webkit-box;
+  -webkit-line-clamp: 2;
+  -webkit-box-orient: vertical;
+  word-break: break-all;
+}
+.control .control_content .control_content-center .device-wrapper .device-list  .content_box {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  align-content: center;
+  padding: 0 25rem;
+  margin-bottom: 15rem;
+  cursor: pointer;
+}
+.control .control_content .control_content-center .device-wrapper .device-list  .content_box:hover {
+  --color:red !important;
+}
+.control .control_content .control_content-center .device-wrapper .device-list  .content_box:hover img {
+  transition: all 0.2s;
+  transform: scale(1.2);
+}
+.control .control_content .control_content-center .device-wrapper .device-list .i {
+  width: 20rem;
+  height: 20rem;
+  border-radius: 20rem;
+  background: red;
+}
+.control .control_content .control_content-center .device-wrapper .device-list img {
+  width: 100%;
+  max-height: 70rem;
+}
+.control .control_content .control_content-center .device-wrapper .device-list .status {
+  color: var(--color2);
+}
+.control .control_content .control_content-center .content_box {
+  height: 100%;
+  margin: 0 18rem;
+  width: auto !important;
+  flex: 1;
+}
+.control .control_content .control_content-center .device-list .content_box {
+  flex: 1 !important;
+  max-width: 212rem;
+}
+.control .control_content .control_content-right {
+  flex: 1;
+  overflow: hidden;
+  height: 100%;
+  display: flex;
+  flex-direction: column;
+}
+.control .control_content .control_content-right .content_box:first-child {
+  margin-bottom: 15rem;
+  height: 35%;
+}
+.control .control_content .control_content-right .content_box:last-child {
+  height: 65%;
+}
+.control .control_content .control_content-right .info-wrapper {
+  height: calc(100% - 30rem);
+  overflow-y: scroll;
+}
+.control .control_content .control_content-right .info-wrapper .info-list {
+}
+.control .control_content .control_content-right .info-wrapper .info-list .info-item {
+  display: flex;
+  justify-content: space-between;
+  margin-bottom: 10rem;
+  cursor: pointer;
+}
+.control .control_content .control_content-right .info-wrapper .info-list .info-item:hover {
+  background: rgba(255, 255, 255, 0.4);
+}
+.control .control_content .control_content-right .info-wrapper .info-list .info-item span {
+  white-space: nowrap;
+  overflow: hidden;
+  text-overflow: ellipsis;
+}
+.control .control_content .control_content-right .info-wrapper .info-list .info-item span:nth-child(1) {
+  flex: 1;
+  
+}
+.control .control_content .control_content-right .info-wrapper .info-list .info-item span:nth-child(2) {
+  flex: 1;
+}
+.control .control_content .control_content-right .info-wrapper .info-list .info-item span:nth-child(3) {
+  flex: 2;
+}
+.control .control_content .control_content-right .info-wrapper .info-list .info-item span:nth-child(1) {
+  color: var(--color1);
+}
+.control .control_content .control_content-right .info-wrapper .info-list .info-item span:nth-child(2) {
+  color: var(--color2);
+}
+
+
+.control .control_content .control_content-right .handle-wrapper {
+  height: calc(100% - 30rem);
+  overflow-y: scroll;
+}
+.control .control_content .control_content-right .handle-wrapper .handle-list {
+}
+.control .control_content .control_content-right .handle-wrapper .handle-list .info-item {
+  display: flex;
+  justify-content: space-between;
+  margin-bottom: 10rem;
+  cursor: pointer;
+}
+.control .control_content .control_content-right .handle-wrapper .handle-list .info-item:hover {
+  background: rgba(255, 255, 255, 0.4);
+}
+.control .control_content .control_content-right .handle-wrapper .handle-list .info-item span {
+  white-space: nowrap;
+  overflow: hidden;
+  text-overflow: ellipsis;
+}
+.control .control_content .control_content-right .handle-wrapper .handle-list .info-item span:nth-child(1) {
+  flex: 1;
+  
+}
+.control .control_content .control_content-right .handle-wrapper .handle-list .info-item span:nth-child(2) {
+  flex: 1;
+}
+.control .control_content .control_content-right .handle-wrapper .handle-list .info-item span:nth-child(3) {
+  flex: 2;
+}
+.control .control_content .control_content-right .handle-wrapper .handle-list .info-item span:nth-child(1) {
+  color: var(--color1);
+}
+.control .control_content .control_content-right .handle-wrapper .handle-list .info-item span:nth-child(2) {
+  color: var(--color2);
+}
+.content_box {
+  padding: 10rem 15rem;
+}
+.move {
+  margin-top: -30rem;
+  transition: all 0.5s ease-in-out;
+}
+</style>

+ 6 - 1
src/operation/moduleNormal/pressureControl/index.vue

@@ -140,7 +140,7 @@
             </div>
           </div>
           <div class="device-wrapper" v-load-directive="deviceLoad">
-            <div class="device-list">
+            <div class="device-list" v-if="data.deviceList.length">
               <ContentBox v-for="(item,index) in data.deviceList" :key="index" bgColor="rgb(255,255,255,0.25)" color="#16FFF6" @click="deviceClick(item)">
                 <div style="height: 30rem;"></div>
                 <div class="siteinfo">
@@ -162,6 +162,11 @@
                 <!-- <span class="status">运行状态:<span class="text" :style="item.eventstatus ? 'color:red' : 'color:rgba(255, 164, 6)'">{{ item.eventstatus ? '告警中' : '正常' }}</span></span> -->
               </ContentBox>
             </div>
+            <a-empty :image="simpleImage" v-else>
+              <template #description>
+                <span style="color:#ffffff">暂无数据</span>
+              </template>
+            </a-empty>
           </div>
         </ContentBox>
       </div>

+ 10 - 0
src/router/index.js

@@ -33,6 +33,16 @@ const routes = [
     },
     component: ()=>import(/* webpackChunkName: "about" */ '@/operation/moduleNormal/pressureControl/index.vue'),
   },
+  {
+    path: '/positionControl',
+    name: 'bg_position',
+    meta: {
+        title: '仪表盘',
+        name: 'bg_position',
+        keepAlive:true
+    },
+    component: ()=>import(/* webpackChunkName: "about" */ '@/operation/moduleNormal/positionControl/index.vue'),
+  },
   {
     path: '/404',
     name: '404',

+ 1 - 1
src/views/controlPanel/index.vue

@@ -77,7 +77,7 @@
               <p>压力管理<br/>系统</p>
               <img src="@/assets/controlPanel/icon/压力管理系统.png" alt="">
             </div>
-            <div class="item" @click="itemClick('')">
+            <div class="item" @click="itemClick('valveadjust')">
               <p>阀位管理<br/>系统</p>
               <img src="@/assets/controlPanel/icon/阀位管理系统.png" alt="">
             </div>

+ 4 - 4
vite.config.js

@@ -12,15 +12,15 @@ export default defineConfig({
   },
   define: {
     'process.env': {
-      // 'BASE_API':"http://61.164.207.46:8100"
-      'BASE_API':"http://60.204.153.188"
+      // 'BASE_API':"http://60.204.153.188"
+      'BASE_API':"http://61.164.207.46:8100/"
     }
   },
   server: {
     proxy: {
       "/api": {
-        // target: "http://61.164.207.46:8100/",
-        target: "http://60.204.153.188/",
+        // target: "http://60.204.153.188/",
+        target: "http://61.164.207.46:8100/",
         ws: true,
         changeOrigin: true,
         rewrite: (path) => path.replace(/^\/api/, ""),