|
@@ -0,0 +1,423 @@
|
|
|
|
+<template>
|
|
|
|
+ <div class="page-container-wpmix">
|
|
|
|
+ <div class="page-left">
|
|
|
|
+ <div class="curve-box">
|
|
|
|
+ <GroupCurve id="wpmix_grpcurve" :initLoad="initLoad" :timeLoad="timeLoad" :height="curveboxH" ref="mixgroupCurveComp" :key="'wpmix_'+crtWell.id"/>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+
|
|
|
|
+ <div class="diagram-box">
|
|
|
|
+ <div class="single-box">
|
|
|
|
+ <div class="single-header">{{crtWell.name?(crtWell.name+'生产主要参数'):'还未选择井'}}</div>
|
|
|
|
+ <div class="single-body">
|
|
|
|
+ <div class="param-block" v-for="(param,index) in singleParams">
|
|
|
|
+ <div class="param-tit">{{param.paramName}}</div>
|
|
|
|
+ <div class="param-val" :class="{'param-val-alarm':patrolAlarm[param.paramCode]}" :title="patrolAlarm[param.paramCode]?.alarmDesc">{{patrolData[param.paramCode]}}</div>
|
|
|
|
+ <div class="param-unit" v-if="param.displayUnit&¶m.displayUnit!='空'">{{param.displayUnit}}</div>
|
|
|
|
+
|
|
|
|
+ </div>
|
|
|
|
+
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ <template v-for="(elModel,index) in diagramParams" :key="index">
|
|
|
|
+ <div class="multi" style="width:405px;height:230px;">
|
|
|
|
+ <div class="multi-header">
|
|
|
|
+ <label>{{elModel.paramName}}</label>
|
|
|
|
+ <div class="multi-tool">
|
|
|
|
+ <el-icon :size="24" title="前一点数据" @click="diagramCtr(elModel.paramCode,'pre')"><CaretLeft /></el-icon>
|
|
|
|
+ <el-icon :size="24" title="后一点数据" @click="diagramCtr(elModel.paramCode,'next')"><CaretRight /></el-icon>
|
|
|
|
+ <el-icon :size="24" title="自动更新" @click="diagramCtr(elModel.paramCode,'last')"><RefreshRight /></el-icon>
|
|
|
|
+ <el-icon :size="24" title="图形回放" @click="diagramCtr(elModel.paramCode,'replay')"><VideoPlay /></el-icon>
|
|
|
|
+ <el-icon :size="24" title="更多" @click="showCtxMenu($event,elModel)"><ArrowRight/></el-icon>
|
|
|
|
+ </div>
|
|
|
|
+
|
|
|
|
+ </div>
|
|
|
|
+ <div class="multi-body">
|
|
|
|
+ <Diagram :id="elModel.paramCode+index+'_wpmix'" :width="400" :height="190" :ref="elModel.paramCode" :axisRatio="1.2" :ctx="{wellId:crtWell.id,paramCode:elModel.paramCode}" :data="loadDiagramData"/>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </template>
|
|
|
|
+ </div>
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ <context-menu
|
|
|
|
+ v-model:show="ctxmenuOpts.show"
|
|
|
|
+ :options="ctxmenuOpts.options"
|
|
|
|
+ >
|
|
|
|
+ <context-menu-item label="历史图形" @click="onMenuClick('WellHisDiagramDialog','历史图形')" />
|
|
|
|
+ </context-menu>
|
|
|
|
+
|
|
|
|
+ <el-dialog v-model="dialogCtr.show" :title="dialogCtr.title" :close-on-click-modal="false" :destroy-on-close="true" width="70%">
|
|
|
|
+ <component :is="dialogInnerComp[dialogCompKey]" :ctxObj="dialogCtx"></component>
|
|
|
|
+ <template #footer>
|
|
|
|
+ <el-button @click="dialogCtr.show=false">关闭</el-button>
|
|
|
|
+ </template>
|
|
|
|
+ </el-dialog>
|
|
|
|
+ </div>
|
|
|
|
+</template>
|
|
|
|
+
|
|
|
|
+<script setup>
|
|
|
|
+ import {reactive,ref,watch,toRaw,onMounted,onUnmounted,nextTick,getCurrentInstance } from 'vue'
|
|
|
|
+ import Diagram from '../../components/diagram/Diagram.vue'
|
|
|
|
+ import wellPatrolAPI from '../../api/wellPatrol.js'
|
|
|
|
+ import wellParamAPI from '../../api/wellParam.js'
|
|
|
|
+ import tempAPI from '../../api/multiTabTemp.js'
|
|
|
|
+ import { storeToRefs } from 'pinia'
|
|
|
|
+ import { useHomeStore } from '../../store/home.js'
|
|
|
|
+ import utils from '@/utils/utils.js'
|
|
|
|
+ import {ElMessageBox,ElMessage} from 'element-plus'
|
|
|
|
+ import WellHisDiagramDialog from '../single/WellHisDiagramDialog.vue'
|
|
|
|
+ import GroupCurve from '../../components/groupCurve/GroupCurve.vue'
|
|
|
|
+
|
|
|
|
+ import '@imengyu/vue3-context-menu/lib/vue3-context-menu.css'
|
|
|
|
+ import '@/assets/css/ContextMenu.css'
|
|
|
|
+ import { ContextMenu, ContextMenuGroup, ContextMenuSeparator, ContextMenuItem } from '@imengyu/vue3-context-menu'
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ let {proxy} = getCurrentInstance()
|
|
|
|
+ //右键菜单配置
|
|
|
|
+ const ctxmenuOpts=reactive({
|
|
|
|
+ show:false,
|
|
|
|
+ type:'single',
|
|
|
|
+ options:{
|
|
|
|
+ zIndex:3,
|
|
|
|
+ minWidth: 230,
|
|
|
|
+ x: 500,
|
|
|
|
+ y: 200
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+
|
|
|
|
+ const showCtxMenu=(event,elModel)=>{
|
|
|
|
+ event.preventDefault()
|
|
|
|
+ ctxmenuOpts.type=elModel.elType
|
|
|
|
+ ctxmenuOpts.show=true
|
|
|
|
+ ctxmenuOpts.options.x=event.x
|
|
|
|
+ ctxmenuOpts.options.y=event.y
|
|
|
|
+ dialogCtx.wellId=crtWell.id
|
|
|
|
+ dialogCtx.wellName=crtWell.name
|
|
|
|
+ dialogCtx.paramCode=elModel.paramCode
|
|
|
|
+ dialogCtx.paramName=elModel.paramName
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ const onMenuClick=(action,actionName)=>{
|
|
|
|
+ dialogCompKey.value=action
|
|
|
|
+ dialogCtr.title=`${actionName}【${dialogCtx.wellName}】`
|
|
|
|
+ dialogCtr.show=true
|
|
|
|
+ }
|
|
|
|
+ //右键菜单配置-结束
|
|
|
|
+
|
|
|
|
+ //弹窗动态组件配置
|
|
|
|
+ const dialogCtr=reactive({
|
|
|
|
+ show:false,
|
|
|
|
+ title:'查看窗口',
|
|
|
|
+
|
|
|
|
+ })
|
|
|
|
+
|
|
|
|
+ const dialogInnerComp={
|
|
|
|
+ WellHisDiagramDialog
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ const dialogCtx=reactive({
|
|
|
|
+ wellName:null,
|
|
|
|
+ wellId:null,
|
|
|
|
+ paramCode:null,
|
|
|
|
+ paramName:null,
|
|
|
|
+ paramId:null
|
|
|
|
+ })
|
|
|
|
+
|
|
|
|
+ const dialogCompKey=ref(null)
|
|
|
|
+ //弹窗动态组件配置-结束
|
|
|
|
+
|
|
|
|
+ const diagramCtr=(paramCode,action)=>{
|
|
|
|
+ let diagramIns=proxy.$refs[paramCode]
|
|
|
|
+ if('replay'==action){
|
|
|
|
+ diagramIns.replay()
|
|
|
|
+ }
|
|
|
|
+ else if('next'==action){
|
|
|
|
+ diagramIns.next()
|
|
|
|
+ }
|
|
|
|
+ else if('pre'==action){
|
|
|
|
+ diagramIns.pre()
|
|
|
|
+ }
|
|
|
|
+ else if('last'==action){
|
|
|
|
+ diagramIns.last()
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ //切换井时进行数据的重置
|
|
|
|
+ const resetPage=()=>{
|
|
|
|
+ if(singleTimer){
|
|
|
|
+ clearInterval(singleTimer)
|
|
|
|
+ singleTimer= null
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ const diagramParams=ref([])
|
|
|
|
+
|
|
|
|
+ const crtWell=reactive({})
|
|
|
|
+
|
|
|
|
+ const loadDiagramData=(reqData)=>{ //Diagram.vue回调该函数
|
|
|
|
+ return wellPatrolAPI.loadDiagram(reqData)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ //单值采集数据获取
|
|
|
|
+ let singleTimer=null
|
|
|
|
+ const singleParams=ref([])
|
|
|
|
+ const patrolData=ref({})
|
|
|
|
+ const patrolAlarm=ref({})
|
|
|
|
+ const loadSingleData=(wellId)=>{
|
|
|
|
+ wellPatrolAPI.loadData(wellId).then(resp=>{
|
|
|
|
+ //console.log(resp)
|
|
|
|
+ if(resp.code!=0||!resp.data){
|
|
|
|
+ ElMessage.error(resp.msg||'未获取到实时数据')
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ Object.assign(patrolData.value,resp.data.data)
|
|
|
|
+ patrolAlarm.value=wellPatrolAPI.processAlarm(resp.data.alarm)
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ }).catch(err=>{
|
|
|
|
+ ElMessage.error('获取实时数据失败')
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ const loadWellParam=(wellId)=>{
|
|
|
|
+ wellParamAPI.loadWellParam(wellId).then(resp=>{
|
|
|
|
+
|
|
|
|
+ if(resp.code!=0){
|
|
|
|
+ ElMessage.error(resp.msg||'获取井参数失败')
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ diagramParams.value=resp.data.filter(param=>param.paramCode.indexOf('diagram')>=0)
|
|
|
|
+ singleParams.value = resp.data.filter(param=>param.paramCode.indexOf('diagram')<0)
|
|
|
|
+
|
|
|
|
+ nextTick(()=>{
|
|
|
|
+ loadSingleData(wellId)
|
|
|
|
+ singleTimer=setInterval(()=>{loadSingleData(wellId)},30000)
|
|
|
|
+ })
|
|
|
|
+
|
|
|
|
+ }).catch(err=>{
|
|
|
|
+
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ //单值采集数据获取-end
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ //分组曲线配置
|
|
|
|
+ const curveboxH=ref(560)
|
|
|
|
+
|
|
|
|
+ const mixgroupCurveComp=ref(null)
|
|
|
|
+
|
|
|
|
+ const loadGrpCurveTemp=(wellId)=>{
|
|
|
|
+ wellPatrolAPI.loadSingleGrpCurveTemp(wellId).then(resp=>{
|
|
|
|
+ //console.log(resp)
|
|
|
|
+ if(resp.code!=0){
|
|
|
|
+ ElMessage.error(resp.msg||'获取分组曲线配置失败')
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ let tempDtl=JSON.parse(resp.data.temp.tempContent)
|
|
|
|
+ bindParamUnit(tempDtl,resp.data.units)
|
|
|
|
+
|
|
|
|
+ let startTime=new Date(utils.getNow('yyyy/MM/dd 00:00:00'))
|
|
|
|
+ mixgroupCurveComp.value.init(tempDtl,startTime)
|
|
|
|
+
|
|
|
|
+ }).catch(err=>{
|
|
|
|
+ console.log(err)
|
|
|
|
+ ElMessage.error('获取分组曲线配置出错')
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ const bindParamUnit=(tempDtl,unitMap)=>{
|
|
|
|
+ if(unitMap==null){
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ tempDtl.panels.forEach(panel=>{
|
|
|
|
+ panel.serials.forEach(serial=>{
|
|
|
|
+ if(!unitMap[serial.code] || unitMap[serial.code]=='空'){
|
|
|
|
+ return true
|
|
|
|
+ }
|
|
|
|
+ serial.title=`${serial.title}(${unitMap[serial.code]})`
|
|
|
|
+ })
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ const initLoad=async (params)=>{
|
|
|
|
+ let panelDatas={}
|
|
|
|
+ let resp=null
|
|
|
|
+ for(let i=0,len=params.length;i<len;i++){
|
|
|
|
+ resp=await wellPatrolAPI.loadGrpCurveData(crtWell.id,params[i]).catch(err=>{
|
|
|
|
+ console.log(err)
|
|
|
|
+ })
|
|
|
|
+
|
|
|
|
+ panelDatas[params[i]]=(resp&&resp.code==0)?resp.data:[]
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+ return Promise.resolve(panelDatas)
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ //定时刷新数据
|
|
|
|
+ const timeLoad=async (params)=>{
|
|
|
|
+ //console.log('time load...',utils.dateFmt(new Date()))
|
|
|
|
+ let panelDatas={}
|
|
|
|
+ let resp=null
|
|
|
|
+ let endDate=utils.getNow()
|
|
|
|
+ let startDate=(new Date()).getTime()-120000
|
|
|
|
+ startDate=utils.dateFmt(new Date(startDate))
|
|
|
|
+ for(let i=0,len=params.length;i<len;i++){
|
|
|
|
+ resp=await wellPatrolAPI.loadGrpCurveData(crtWell.id,params[i],startDate,endDate).catch(err=>{
|
|
|
|
+ console.log(err)
|
|
|
|
+ })
|
|
|
|
+
|
|
|
|
+ panelDatas[params[i]]=(resp&&resp.code==0)?resp.data:[]
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+ return Promise.resolve(panelDatas)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ //分组曲线配置结束
|
|
|
|
+
|
|
|
|
+ onMounted(()=>{
|
|
|
|
+ let pagebox=document.querySelector('.el-tabs__content').getBoundingClientRect()
|
|
|
|
+ curveboxH.value=pagebox.height-24
|
|
|
|
+ })
|
|
|
|
+
|
|
|
|
+ onUnmounted(()=>{
|
|
|
|
+ resetPage()
|
|
|
|
+ })
|
|
|
|
+
|
|
|
|
+ const store=useHomeStore()
|
|
|
|
+ const {currentTreeNode} = storeToRefs(store)
|
|
|
|
+
|
|
|
|
+ watch(currentTreeNode,(newNode, oldNode)=>{
|
|
|
|
+ if(newNode&&newNode.nodeType=='well'){
|
|
|
|
+ crtWell.id=newNode.id
|
|
|
|
+ crtWell.name=newNode.name
|
|
|
|
+ resetPage()
|
|
|
|
+ loadWellParam(newNode.id)
|
|
|
|
+ loadGrpCurveTemp(newNode.id)
|
|
|
|
+ }
|
|
|
|
+ },{ immediate: true })
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+</script>
|
|
|
|
+
|
|
|
|
+<style scoped>
|
|
|
|
+ @import url('../../assets/css/wellPatrol.css');
|
|
|
|
+ .page-container-wpmix{
|
|
|
|
+
|
|
|
|
+ height: 100%;
|
|
|
|
+ box-sizing: border-box;
|
|
|
|
+ padding:2px;
|
|
|
|
+ position: relative;
|
|
|
|
+ display: flex;
|
|
|
|
+ flex-flow: row nowrap;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ .diagram-box{
|
|
|
|
+ width:410px;
|
|
|
|
+ border:1px solid #ccc;
|
|
|
|
+ border-left:2px solid #ccc;
|
|
|
|
+ height: 100%;
|
|
|
|
+ overflow-y: auto;
|
|
|
|
+ overflow-x:hidden;
|
|
|
|
+ }
|
|
|
|
+ .diagram-box .multi{
|
|
|
|
+ position: relative;
|
|
|
|
+ }
|
|
|
|
+ .diagram-box .single-box{
|
|
|
|
+ padding:0px;
|
|
|
|
+ border:1px solid #ccc;
|
|
|
|
+ border-radius: 2px;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+ .page-left{
|
|
|
|
+ flex:1 0 0;
|
|
|
|
+ box-sizing: border-box;
|
|
|
|
+ padding-bottom:2px;
|
|
|
|
+ height: 100%;
|
|
|
|
+ overflow-x: auto;
|
|
|
|
+ }
|
|
|
|
+ .curve-box{
|
|
|
|
+ box-sizing: border-box;
|
|
|
|
+ padding:0px;
|
|
|
|
+ height: v-bind(curveboxH)
|
|
|
|
+ /* display:none; */
|
|
|
|
+ }
|
|
|
|
+ .single-header{
|
|
|
|
+ font-size:14px;
|
|
|
|
+ font-weight: bolder;
|
|
|
|
+ text-align: center;
|
|
|
|
+ background-color: #f2f2f2;
|
|
|
|
+ padding:5px;
|
|
|
|
+ }
|
|
|
|
+ .single-body{
|
|
|
|
+ display: grid;
|
|
|
|
+ grid-template-columns: repeat(auto-fill,180px);
|
|
|
|
+ grid-template-rows: repeat(auto-fill,30px);
|
|
|
|
+ grid-gap:10px 15px;
|
|
|
|
+ justify-content: center;
|
|
|
|
+ }
|
|
|
|
+ .single-body .param-block{
|
|
|
|
+ font-size:14px;
|
|
|
|
+ vertical-align:baseline;
|
|
|
|
+ display: flex;
|
|
|
|
+ flex-flow:row nowrap;
|
|
|
|
+ align-items: center;
|
|
|
|
+ color:#555;
|
|
|
|
+ height: 28px;
|
|
|
|
+ box-sizing: border-box;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .param-block .param-tit{
|
|
|
|
+ width:60px;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .param-block .param-val{
|
|
|
|
+ background-color: #fff;
|
|
|
|
+ /* width:60px; */
|
|
|
|
+ text-align: right;
|
|
|
|
+ flex:1;
|
|
|
|
+ padding:5px;
|
|
|
|
+ height: 100%;
|
|
|
|
+ box-sizing: border-box;
|
|
|
|
+ border:1px solid #e4e4e4;
|
|
|
|
+ border-top-left-radius: 3px;
|
|
|
|
+ border-bottom-left-radius: 3px;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .param-block .param-val-alarm{
|
|
|
|
+ background-color: #d04029;
|
|
|
|
+ color: #ffff00;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .param-block .param-unit{
|
|
|
|
+ background-color: #f2f2f2;
|
|
|
|
+ padding:5px 0px;
|
|
|
|
+ border:1px solid #e4e4e4;
|
|
|
|
+ border-left:0px;
|
|
|
|
+ font-size: 12px;
|
|
|
|
+ height: 100%;
|
|
|
|
+ width:40px;
|
|
|
|
+ box-sizing: border-box;
|
|
|
|
+ text-align: center;
|
|
|
|
+ border-top-right-radius: 3px;
|
|
|
|
+ border-bottom-right-radius: 3px;
|
|
|
|
+ }
|
|
|
|
+</style>
|