소스 검색

增加多井分组曲线模板管理模块,增加多井曲线模块

chenwen 1 년 전
부모
커밋
ed1d8fc431
3개의 변경된 파일579개의 추가작업 그리고 0개의 파일을 삭제
  1. 8 0
      src/api/multiSort.js
  2. 346 0
      src/pages/base/MultiGroupCurveTemp.vue
  3. 225 0
      src/pages/multi/MultiCurve.vue

+ 8 - 0
src/api/multiSort.js

@@ -34,4 +34,12 @@ api.loadWellAlarms=(wellIds)=>{
 	});
 }
 
+api.loadMultiParamUnit=(wellIds,paramCodes)=>{
+	return request({
+	    url: '/multisort/loadMultiParamUnit',
+	    method: 'post',
+		data:  {wellIds,paramCodes}
+	});
+}
+
 export  default api

+ 346 - 0
src/pages/base/MultiGroupCurveTemp.vue

@@ -0,0 +1,346 @@
+<template>
+	<div class="page-container">
+		<div class="tool-bar">
+			<el-select v-model="formModel.tempId" placeholder="选择多井分组曲线模板" @change="changeTempHandle">
+				<el-option value="-1" label="空白模板"/>
+				<el-option
+				  v-for="(item,index) in tempbases"
+				  :key="item.tempId"
+				  :label="item.tempName"
+				  :value="item.tempId"
+				/>
+			</el-select>
+			<el-button-group>
+			    <el-button type="primary" icon="Folder" @click="saveTemp('save')">保存</el-button>
+			    <el-button type="primary" icon="FolderAdd" @click="saveTemp('saveAs')">另存为</el-button>
+			    <el-button type="primary" icon="Delete" @click="delTemp">删除</el-button>
+			</el-button-group>
+			
+			<el-form-item label="面板宽" style="margin:0px 20px;">
+			      <el-input-number v-model="formModel.panelWidth" style="width:120px;" :min="200" :max="500"/>
+			</el-form-item>
+			<el-form-item label="面板头高">
+			      <el-input-number v-model="formModel.headerH" style="width:120px;" :min="100" :max="300"/>
+			</el-form-item>
+		</div>
+		
+		<div class="temp-area">
+			<div class="panel-item" v-for="(panel,index) in panels" :key="index">
+				<div class="panel-header">
+					<div class="serial-item" v-for="(serial,idx) in panel.serials" :key="idx">
+						<el-input-number v-model="serial.min" :precision="1" :controls="false" :min="0"/>
+						<label>{{serial.title}}</label>
+						<el-input-number v-model="serial.max" :precision="1" :controls="false" :min="0"/>
+					</div>
+				</div>
+				<div class="panel-body">
+					<el-select v-model="panel.codes" :multiple-limit="5" collapse-tags collapse-tags-tooltip placeholder="选择参数" multiple  @change="changeParamHandle(panel)">
+						<el-option v-for="param in paramCodes" :key="param.paramCode" :label="param.paramName" :value="param.paramCode"/>
+					</el-select>
+					
+				</div>
+				
+			</div>
+			
+		</div>
+	</div>
+</template>
+
+<script setup>
+	import {reactive,ref, toRaw,onMounted,computed} from 'vue'
+	import {ElMessageBox,ElMessage} from 'element-plus'
+	import api from '../../api/multiTabTemp.js'
+	
+	const formModel = reactive({
+		tempId:null,
+		headerH:180,
+		panelWidth:240
+	})
+	
+	const tempbases=ref([])
+	
+	const paramCodes=ref(null)
+	
+	const paramMap={}
+	
+	const panels=ref([
+		{
+			/*serials:[{
+				title:null,
+				min:null,
+				max:null,
+				code:null
+			}],
+			codes:null*/
+		}
+		
+	])
+	
+	onMounted(()=>{
+		loadTemps()
+		loadParamType()
+	})
+	
+	const addPanel=()=>{
+		panels.value.push({
+			serials:null,
+			codes:null,
+		})
+	}
+	
+	const delPanel=(idx)=>{
+		panels.value.splice(idx,1)
+	}
+	
+	const resetPage=()=>{
+		formModel.headerH=180
+		formModel.panelWidth=240
+		panels.value=[{}]
+	}
+	
+	const loadTemps=()=>{
+		api.loadTemps('multiGroup').then(resp=>{
+			if(resp.code==0){
+				tempbases.value=resp.data
+			}
+		}).catch(error=>{
+			
+		})
+	}
+	
+	const loadParamType=()=>{
+		api.loadParamType().then(resp=>{
+			if(resp.code==0){
+				resp.data.forEach((param,idx)=>{
+					if(param.paramCode.indexOf('diagram')<0){
+						paramMap[param.paramCode]=param
+					}
+					
+				})
+				paramCodes.value=Object.values(paramMap) //.filter(d=>d.paramCode.indexOf('diagram')<0)
+			}
+		}).catch(error=>{
+			
+		})
+	}
+	
+	const changeParamHandle=(panel)=>{
+		let newSerials=[]
+		if(!panel.serials||panel.serials.length==0){
+			panel.codes.forEach(code=>{
+				newSerials.push({
+					title:paramMap[code].paramName,
+					min:0,
+					max:10,
+					code
+				})
+			})
+			panel.serials=newSerials
+			return
+		}
+		
+		let codestr='#'+panel.codes.join('#')
+		panel.serials.forEach(serial=>{
+			if(codestr.indexOf(serial.code)>=0){
+				newSerials.push(serial)
+				codestr=codestr.replace(('#'+serial.code),'')
+			}
+		})
+		if(codestr.length>1){
+			codestr=codestr.replace(/^#/,'')
+			codestr=codestr.split('#')
+			codestr.forEach(code=>{
+				newSerials.push({
+					title:paramMap[code].paramName,
+					min:0,
+					max:10,
+					code
+				})
+			})
+		}
+		
+		panel.serials=newSerials
+	}
+	
+	//选择模板后,加载明细
+	const changeTempHandle=(val)=>{
+		resetPage()
+		if(val=="-1"){  //空白模板
+			return
+		}
+		api.getTempDtl(val).then(resp=>{
+			if(resp.code!=0){
+				ElMessage.error(err||'加载模板明细失败')
+				return
+			}
+			if(resp.data&&resp.data.tempContent){
+				let tempConfig=JSON.parse(resp.data.tempContent)
+				//console.log(tempConfig)
+				formModel.headerH=tempConfig.headerH
+				formModel.panelWidth=tempConfig.panelWidth
+				panels.value=tempConfig.panels
+			}
+			
+		}).catch(err=>{
+			   
+		   }
+		)
+	}
+	
+	const getSaveData=()=>{
+		let temDtl={panelWidth:formModel.panelWidth,headerH:formModel.headerH,panels:panels.value}
+		return {tempId:formModel.tempId,tempContent:JSON.stringify(temDtl),tempType:'multiGroup'}
+	}
+	
+	const getSaveTempName=()=>{
+		if(tempbases.value&&tempbases.value.length>0){
+			let temps=tempbases.value.filter(temp=>temp.tempId==formModel.tempId)
+			return temps&&temps.length>0?temps[0].tempName:null
+		}
+		return null
+	}
+	
+	//保存
+	const saveTemp=(tag)=>{
+		let saveAPI=tag=='saveAs'?api.saveAs:api.save
+		return ElMessageBox.prompt('创建新模板',null,{
+		   		   showCancelButton:true,
+		   		   showInput:true,
+				   inputType:'text',
+				   inputValue:getSaveTempName(),
+				   inputPlaceholder:'请输入模板名称',
+				   inputPattern:/\S+/,
+				   inputErrorMessage:'模板名称不能为空',
+				   closeOnClickModal:false
+				}).then(({value })=>{
+					let saveData=getSaveData()
+					//console.log(saveData)
+					saveData['tempName']=value 
+					saveAPI(saveData).then(resp=>{
+						if(resp.code!=0){
+							ElMessage.error(resp.msg||'操作失败')
+						}
+						else{
+							ElMessage.success('操作成功')
+							loadTemps()
+							formModel.tempId=resp.data
+						}
+					})
+					
+				})
+				.catch(err => {
+					console.log('cancel save as '+err)
+				})
+			
+		
+	}
+	
+	//删除
+	const delTemp=()=>{
+		if(formModel.tempId==null||formModel.tempId=="-1"){
+			ElMessage.error('还未选择模板')
+			return
+		}
+		ElMessageBox.confirm(
+			'确定要删除该模板吗?',
+			'操作确认',
+			{
+				confirmButtonText:'确定',
+				cancelButtonText:'取消',
+				type: 'warning'
+			}
+		).then(()=>{
+			api.del(formModel.tempId).then(resp=>{
+				if(resp.code!=0){
+					ElMessage.error(resp.msg)
+					return
+				}
+				ElMessage.success('操作成功')
+				formModel.tempId=null
+				resetPage()
+				loadTemps()
+				
+			}).catch(err=>{
+				ElMessage.error(err||'操作失败')
+			})
+		}).catch(()=>{
+			console.log('cancel del')
+		})
+	}
+</script>
+
+<style scoped>
+	.page-container{
+		height:100%;
+		box-sizing: border-box;
+			
+	}
+	
+	.tool-bar{
+		height:45px;
+		box-sizing: border-box;
+		padding: 5px 10px;
+		margin-bottom: 10px;
+		display: flex;
+		flex-flow:row nowrap;
+		
+	}
+	
+	.temp-area{
+		box-sizing: border-box;
+		padding:10px;
+		display: flex;
+		flex-flow: row nowrap;
+		width:auto;
+		overflow: auto;
+	}
+	
+	.temp-area .panel-item{
+		border:1px solid #d2d2d2;
+		width:v-bind(formModel.panelWidth+'px');
+		height:500px;
+		box-sizing: border-box;
+		margin-right:10px;
+		flex-shrink:0;
+		display: flex;
+		flex-flow:column nowrap;
+		justify-content: space-between;
+		align-items: center;
+	}
+	
+	.temp-area .panel-item .panel-header{
+		height: v-bind(formModel.headerH+'px');
+		border-bottom: 1px solid #00aaff;
+		width:100%;
+	}
+	
+	.panel-header .serial-item{
+		display: flex;
+		flex-flow: row nowrap;
+		justify-content: space-between;
+		align-items: center;
+		font-size:14px;
+		border-bottom: 1px solid #d2d2d2;
+	}
+	.panel-item .panel-body{
+		flex:1;
+		width:100%;
+		display: flex;
+		flex-flow:column nowrap;
+		justify-content: space-between;
+		align-items: center;
+		box-sizing: border-box;
+		padding:10px;
+	}
+	.panel-body .del-icon{
+		cursor: pointer;
+	}
+	.serial-item .el-input-number{
+		width:80px;
+		height:28px;
+		
+	}
+	.serial-item:deep(.el-input-number .el-input__wrapper) {
+		padding:2px 4px;
+	}
+</style>

+ 225 - 0
src/pages/multi/MultiCurve.vue

@@ -0,0 +1,225 @@
+<template>
+	<div class="page-multicurve">
+		<div class="top">
+			<div style="width:200px;"><label>井站:</label>{{crtOrg.name}}</div>
+			<el-form :inline="true" :model="queryForm" class="query-form-inline"  label-width="auto">
+			  <el-form-item label=" ">
+				<el-select v-model="queryForm.wellId"  placeholder="请选择油井" style="width:400px"
+				:multiple-limit="5" collapse-tags collapse-tags-tooltip :max-collapse-tags="3" multiple>
+				  	<el-option 
+					v-for="(well,index) in wells"
+					:key="index"
+					:label="well.wellName"
+					:value="well.wellId"
+					/>
+				    
+				</el-select>
+			  </el-form-item>
+			 <el-form-item label=" ">
+			  	<el-select v-model="queryForm.tempId"  placeholder="请选择模板" style="width:200px">
+			  	  	<el-option
+			  	  	v-for="(temp,index) in temps"
+			  	  	:key="index"
+			  	  	:label="temp.tempName"
+			  	  	:value="temp.tempId"
+			  	  	>
+					</el-option>
+			  	</el-select>			
+			  </el-form-item>
+			  <el-button type="primary" @click="startShow">确定</el-button>
+			</el-form>
+			  
+			  
+			 
+		</div>
+		<div class="page-body">
+			<GroupCurve id="multicurve_grpcurve" :initLoad="initLoad" :timeLoad="timeLoad" :height="curveboxH" ref="multigroupCurveComp" :key="'multicurve_'+grpcurvecomKey.key"/>
+		</div>
+	</div>
+</template>
+
+<script setup>
+	import {reactive,ref,watch,onMounted, nextTick} from 'vue'
+	import { storeToRefs } from 'pinia'
+	import { useHomeStore } from '../../store/home.js'
+	import {ElMessage} from 'element-plus'
+	
+	import multiSortAPI from '../../api/multiSort.js'
+	import multiTabTempAPI from '../../api/multiTabTemp.js'
+	import wellPatrolAPI from '../../api/wellPatrol.js'
+	import utils from '@/utils/utils.js'
+	
+	import GroupCurve from '../../components/groupCurve/GroupCurve.vue'
+	
+	const crtOrg=reactive({})
+	const wells=ref([])
+	let wellMap=null
+	const temps=ref([])
+	
+	const queryForm=reactive({
+		wellId:null,
+		tempId:null
+	})
+	
+	const loadWells=(orgId)=>{
+		multiSortAPI.loadWells(orgId,100).then(resp=>{
+			if(resp.code!=0){
+				ElMessage.error(resp.msg)
+				return
+			}
+			wells.value=resp.data.data
+			wellMap={}
+			wells.value.forEach(well=>{
+				wellMap[well.wellId]=well
+			})
+		}).catch(err=>{
+			console.log(err)
+		})
+	}
+	
+	const loadTemps=(orgId)=>{
+		
+		multiTabTempAPI.loadTemps('multiGroup').then(resp=>{
+			if(resp.code==0){
+				temps.value=resp.data
+			}
+		}).catch(error=>{
+			console.log(err)
+		})
+	}
+	
+	loadTemps()
+	
+	
+	//分组曲线配置
+	const grpcurvecomKey=reactive({key:Math.random()+'mc'})  //组件动态key
+	const curveboxH=ref(560)
+	const multigroupCurveComp=ref(null)
+	
+	const startShow=async ()=>{
+		if(!queryForm.wellId || !queryForm.tempId){
+			ElMessage.error('请先选择井和模板再继续')
+			return
+		}
+		grpcurvecomKey.key=Math.random()+'mc'  //通过更改组件key,禁止组件复用,key变更后会调用组件onUnmounted销毁,再重新创建
+		
+		let selTemp=temps.value.filter(temp=>temp.tempId==queryForm.tempId)
+		
+		let tempDtl=JSON.parse(selTemp[0].tempContent)
+		let resp=await multiSortAPI.loadMultiParamUnit(queryForm.wellId.join(','),tempDtl.panels[0].codes.join(',')).catch(err=>{
+			console.log('loadMultiParamUnit:',err)
+		})
+		buildMultiWellTemp(tempDtl,resp.code==0?resp.data:null)
+		
+		let startTime=new Date(utils.getNow('yyyy/MM/dd 00:00:00'))
+		multigroupCurveComp.value.init(tempDtl,startTime)
+	}
+	
+	
+	
+	//构建多井面板配置
+	const buildMultiWellTemp=(temp,units)=>{
+		let panelJson=JSON.stringify(temp.panels.pop())
+		queryForm.wellId.forEach(wid=>{
+			let len=temp.panels.push(Object.assign({panelId:wid,panelTitle:wellMap[wid]['wellName']},JSON.parse(panelJson)))
+			bindParamUnit(temp.panels[len-1],units?units[wid]:null)
+			
+		})
+	}
+	//绑定参数单位
+	const bindParamUnit=(panel,unitMap)=>{
+		if(unitMap==null){
+			return
+		}
+		panel.serials.forEach(serial=>{
+			if(!unitMap[serial.code] || unitMap[serial.code]=='空'){
+				return true
+			}
+			serial.title=`${serial.title}(${unitMap[serial.code]})`
+		})
+	}
+	
+	const initLoad=async (params,panelConfig)=>{
+		let panelDatas={}
+		let resp=null
+		for(let i=0,len=params.length;i<len;i++){
+			resp=await wellPatrolAPI.loadGrpCurveData(panelConfig.panelId,params[i]).catch(err=>{
+				console.log(err)
+			})
+			
+			panelDatas[params[i]]=(resp&&resp.code==0)?resp.data:[]
+			
+		}
+		return Promise.resolve(panelDatas)
+	}
+	
+	//定时刷新数据
+	const timeLoad=async (params,panelConfig)=>{
+		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(panelConfig.panelId,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-40
+	})
+	
+	const store=useHomeStore()
+	const  {currentTreeNode} = storeToRefs(store)
+	watch(currentTreeNode,(newNode, oldNode)=>{
+			if(newNode&&newNode.nodeType=='org'){
+				crtOrg.id=newNode.id
+				crtOrg.name=newNode.name
+				
+				loadWells(newNode.id)
+			}
+	},{ immediate: true })
+</script>
+
+<style scoped>
+	.page-multicurve{
+		width:100%;
+		height: 100%;
+		box-sizing: border-box;
+		display: flex;
+		flex-flow:column nowrap;
+		
+	}
+	
+	.top{
+		height:30px;
+		line-height: 30px;
+		padding:5px;
+		background-color:#f0f9ff;
+		font-size: 14px;
+		display: flex;
+		flex-flow:row nowrap;
+		align-items: center;
+		justify-content: space-between;
+	}
+	
+	.top label{
+		color:#555;
+	}
+	.el-form-item{
+		margin-bottom:0px;
+	}
+	
+	.page-body{
+		flex:1;
+	}
+</style>