|
|
@@ -1,5 +1,42 @@
|
|
|
<template>
|
|
|
<div class="page">
|
|
|
+ <!-- 新增信息展示栏 -->
|
|
|
+ <div class="info-row">
|
|
|
+ <div class="info-item">
|
|
|
+ <label>井号:</label>
|
|
|
+ <span class="highlight">{{ infoModel.jh }}</span>
|
|
|
+ </div>
|
|
|
+ <div class="info-item">
|
|
|
+ <label>最新时间:</label>
|
|
|
+ <span class="highlight">{{ infoModel.latestTime }}</span>
|
|
|
+ </div>
|
|
|
+ <div class="info-item">
|
|
|
+ <label>当前工况:</label>
|
|
|
+ <span :class="infoModel.workConditionClass">{{ infoModel.workCondition }}</span>
|
|
|
+ </div>
|
|
|
+ <div class="info-item">
|
|
|
+ <label>当前风险:</label>
|
|
|
+ <span class="risk-status">
|
|
|
+ <span class="risk-item" v-for="(risk, index) in infoModel.riskStatus" :key="index" :style="{ color: risk.color }">
|
|
|
+ {{ risk.name }}: {{ risk.level }}
|
|
|
+ </span>
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 新增日期查询 -->
|
|
|
+ <div class="filter-row">
|
|
|
+ <el-date-picker
|
|
|
+ v-model="endDate"
|
|
|
+ type="date"
|
|
|
+ placeholder="选择结束日期"
|
|
|
+ value-format="yyyy-MM-dd"
|
|
|
+ :picker-options="pickerOptions"
|
|
|
+ style="width: 240px; margin-right: 15px;"
|
|
|
+ />
|
|
|
+ <el-button type="primary" @click="handleDateQuery" icon="el-icon-search">查询</el-button>
|
|
|
+ </div>
|
|
|
+
|
|
|
<!-- 顶部状态卡片 -->
|
|
|
<div class="head">
|
|
|
<div class="head-card" v-for="(card, index) in headCards" :key="index" :style="{ backgroundColor: card.color }">
|
|
|
@@ -49,7 +86,8 @@
|
|
|
</thead>
|
|
|
<tbody>
|
|
|
<tr v-for="(item, i) in chart.data" :key="i">
|
|
|
- <td>{{ formatTime(i) }}</td>
|
|
|
+ <td>{{ formatTime(chart.timeStamps[i]) }}</td>
|
|
|
+ <!-- 使用实际时间 -->
|
|
|
<td>{{ item }}%</td>
|
|
|
<td :class="getStatusClass(item)">
|
|
|
{{ getStatusText(item) }}
|
|
|
@@ -70,19 +108,32 @@
|
|
|
</template>
|
|
|
|
|
|
<script>
|
|
|
-import * as echarts from 'echarts';
|
|
|
-import { throttle } from 'lodash-es';
|
|
|
-
|
|
|
+import * as echarts from 'echarts'
|
|
|
+import { throttle } from 'lodash-es'
|
|
|
+import drillingRiskApi from '@api/drillingRiskApi'
|
|
|
+import moment from 'moment'
|
|
|
+import { filter } from 'vuedraggable'
|
|
|
export default {
|
|
|
name: 'SingleWellWarnInfo',
|
|
|
data() {
|
|
|
return {
|
|
|
+ infoModel:{
|
|
|
+ jh:'草27-侧平12',
|
|
|
+ latestTime: '2023-09-16 08:08:08',
|
|
|
+ workCondition: '起下钻',
|
|
|
+ workConditionClass: 'condition-normal',
|
|
|
+ riskStatus: [
|
|
|
+ { name: '卡钻', level: '高', color: '#ff4d4f' },
|
|
|
+ { name: '井漏', level: '中', color: '#faad14' },
|
|
|
+ { name: '溢流', level: '低', color: '#52c41a' }
|
|
|
+ ],
|
|
|
+ },
|
|
|
chartHeight: '400px',
|
|
|
- currentView: 'day',
|
|
|
+ currentView: '1',
|
|
|
views: [
|
|
|
- { label: '日视图', value: 'day' },
|
|
|
- { label: '周视图', value: 'week' },
|
|
|
- { label: '月视图', value: 'month' }
|
|
|
+ { label: '日视图', value: '1' },
|
|
|
+ { label: '周视图', value: '2' },
|
|
|
+ { label: '月视图', value: '3' }
|
|
|
],
|
|
|
allCharts: [],
|
|
|
visibleCharts: [],
|
|
|
@@ -90,67 +141,180 @@ export default {
|
|
|
currentPage: 1,
|
|
|
loading: false,
|
|
|
showTables: [],
|
|
|
- headCards: [{ value: 1000, label: '钩载异常', color: '#6DA9E4' },
|
|
|
- { value: 1000, label: '扭矩异常', color: '#7ED957' },
|
|
|
- { value: 1000, label: '泵压异常', color: '#FFB347' },
|
|
|
- { value: 1000, label: '总池体积异常', color: '#FF6B6B' }]
|
|
|
- };
|
|
|
+ headCards: [
|
|
|
+ { value: 1000, label: '钩载异常', color: '#6DA9E4' },
|
|
|
+ { value: 1000, label: '扭矩异常', color: '#7ED957' },
|
|
|
+ { value: 1000, label: '泵压异常', color: '#FFB347' },
|
|
|
+ { value: 1000, label: '总池体积异常', color: '#FF6B6B' }
|
|
|
+ ],
|
|
|
+ endDate: new Date().toISOString().split('T')[0], // 默认当天
|
|
|
+ pickerOptions: {
|
|
|
+ shortcuts: [
|
|
|
+ {
|
|
|
+ text: '最近三天',
|
|
|
+ onClick(picker) {
|
|
|
+ const date = new Date()
|
|
|
+ date.setDate(date.getDate() - 2)
|
|
|
+ picker.$emit('pick', date)
|
|
|
+ }
|
|
|
+ },
|
|
|
+ {
|
|
|
+ text: '最近一周',
|
|
|
+ onClick(picker) {
|
|
|
+ const date = new Date()
|
|
|
+ date.setDate(date.getDate() - 6)
|
|
|
+ picker.$emit('pick', date)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ }
|
|
|
},
|
|
|
created() {
|
|
|
- this.generateChartData();
|
|
|
},
|
|
|
mounted() {
|
|
|
- this.initCharts();
|
|
|
- window.addEventListener('resize', this.handleResize);
|
|
|
+ this.infoModel.jh = this.$route.query.jh
|
|
|
+ console.log('this.$route.query.jh',this.$route.query.jh)
|
|
|
+ this.getRealDataByJh()
|
|
|
+ this.initCharts()
|
|
|
+ this.loadChartData()
|
|
|
+ window.addEventListener('resize', this.handleResize)
|
|
|
+ this.getWarnCountByJhAndDate()
|
|
|
+
|
|
|
},
|
|
|
beforeDestroy() {
|
|
|
- window.removeEventListener('resize', this.handleResize);
|
|
|
+ window.removeEventListener('resize', this.handleResize)
|
|
|
},
|
|
|
methods: {
|
|
|
- generateChartData() {
|
|
|
- // 生成模拟数据
|
|
|
- this.allCharts = [
|
|
|
- { id: 1, title: '卡钻风险', data: this.generateRandomData() },
|
|
|
- { id: 2, title: '井漏风险', data: this.generateRandomData() },
|
|
|
- { id: 3, title: '溢流风险', data: this.generateRandomData() },
|
|
|
- // 添加更多测试数据...
|
|
|
- ];
|
|
|
- this.visibleCharts = this.allCharts.slice(0, this.pageSize);
|
|
|
- this.showTables = new Array(this.visibleCharts.length).fill(false);
|
|
|
- },
|
|
|
+ getRealDataByJh(){
|
|
|
+ var param={
|
|
|
+ jh:this.infoModel.jh
|
|
|
+ }
|
|
|
+ drillingRiskApi.getRealDataByJh(param).then(res=>{
|
|
|
+ console.log('井实时数据',res)
|
|
|
+ if(res.success){
|
|
|
+ this.infoModel.latestTime= res.result[0].warnTime
|
|
|
+ this.infoModel.workCondition= res.result[0].workingCondition+'-'+res.result[0].motion
|
|
|
+ // this.infoModel=res.result
|
|
|
+ this.infoModel.riskStatus.forEach(item=>{
|
|
|
+ let itemRes=res.result.filter(items=>items.warnType==item.name)
|
|
|
+ item.level=this.judgeRisk(itemRes[0].warnLevel)
|
|
|
+ })
|
|
|
+
|
|
|
+ }
|
|
|
+ })
|
|
|
|
|
|
- generateRandomData() {
|
|
|
- return Array.from({ length: this.getDataLength() }, () =>
|
|
|
- Math.floor(Math.random() * 100)
|
|
|
- );
|
|
|
},
|
|
|
+ judgeRisk(warnLevel){
|
|
|
+ if (warnLevel >= 80) {
|
|
|
+ return '高'
|
|
|
+ } else if (warnLevel >= 50) {
|
|
|
+ return '中'
|
|
|
+ } else {
|
|
|
+ return '低'
|
|
|
+ }
|
|
|
+ },
|
|
|
+ handleDateQuery() {
|
|
|
+ this.getWarnCountByJhAndDate()
|
|
|
+ this.loadChartData()
|
|
|
+ this.getLogByJh()
|
|
|
+ this.$nextTick(() => {
|
|
|
+ this.initCharts()
|
|
|
+ })
|
|
|
+ },
|
|
|
+ getWarnCountByJhAndDate() {
|
|
|
+ var param = {
|
|
|
+ startDate: this.endDate + ' 00:00:00',
|
|
|
+ endDate: this.endDate + ' 23:59:59',
|
|
|
+ jh: this.infoModel.jh
|
|
|
+ }
|
|
|
+ drillingRiskApi.getWarnCountByJhAndDate(param).then(res => {
|
|
|
+ if (res.success) {
|
|
|
+ this.headCards[0].value = res.result.gzCount
|
|
|
+ this.headCards[1].value = res.result.njCount
|
|
|
+ this.headCards[2].value = res.result.byCount
|
|
|
+ this.headCards[3].value = res.result.jlCount + res.result.ylCount
|
|
|
+ }
|
|
|
+ })
|
|
|
+ },
|
|
|
+
|
|
|
+ async loadChartData() {
|
|
|
+ try {
|
|
|
+ // 并行获取三种风险数据
|
|
|
+ const [qzRes, jlRes, ylRes] = await Promise.all([
|
|
|
+ this.getLogByJh(this.endDate, this.infoModel.jh, this.currentView, '卡钻'),
|
|
|
+ this.getLogByJh(this.endDate, this.infoModel.jh, this.currentView, '井漏'),
|
|
|
+ this.getLogByJh(this.endDate, this.infoModel.jh, this.currentView, '溢流')
|
|
|
+ ])
|
|
|
+
|
|
|
+ // 时间对齐处理逻辑
|
|
|
+ const processData = data => {
|
|
|
+ // 按时间升序排序
|
|
|
+ const sortedData = data.sort((a, b) => new Date(a.warnTime) - new Date(b.warnTime))
|
|
|
+
|
|
|
+ return {
|
|
|
+ timeStamps: sortedData.map(d => d.warnTime),
|
|
|
+ values: sortedData.map(d => d.warnLevel)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 处理各风险数据
|
|
|
+ const chartData = {
|
|
|
+ 卡钻风险: processData(qzRes),
|
|
|
+ 井漏风险: processData(jlRes),
|
|
|
+ 溢流风险: processData(ylRes)
|
|
|
+ }
|
|
|
|
|
|
+ // 生成图表配置
|
|
|
+ this.allCharts = Object.entries(chartData).map(([title, data], index) => ({
|
|
|
+ id: index + 1,
|
|
|
+ title,
|
|
|
+ data: data.values,
|
|
|
+ timeStamps: data.timeStamps // 保存时间序列用于表格显示
|
|
|
+ }))
|
|
|
+
|
|
|
+ this.visibleCharts = this.allCharts.slice(0, this.pageSize)
|
|
|
+ this.$nextTick(this.initCharts)
|
|
|
+ } catch (error) {
|
|
|
+ console.error('数据加载失败:', error)
|
|
|
+ }
|
|
|
+ },
|
|
|
+ async getLogByJh(endDate, jh, dateType, warnType) {
|
|
|
+ var param = {
|
|
|
+ endDate: endDate,
|
|
|
+ jh: jh,
|
|
|
+ dateType: dateType,
|
|
|
+ warnType: warnType
|
|
|
+ }
|
|
|
+ var res = await drillingRiskApi.getLogByJh(param)
|
|
|
+ return res.result
|
|
|
+ },
|
|
|
getDataLength() {
|
|
|
switch (this.currentView) {
|
|
|
- case 'day': return 24;
|
|
|
- case 'week': return 7;
|
|
|
- case 'month': return 30;
|
|
|
- default: return 24;
|
|
|
+ case 'day':
|
|
|
+ return 24
|
|
|
+ case 'week':
|
|
|
+ return 7
|
|
|
+ case 'month':
|
|
|
+ return 30
|
|
|
+ default:
|
|
|
+ return 24
|
|
|
}
|
|
|
},
|
|
|
|
|
|
- formatTime(index) {
|
|
|
- if (this.currentView === 'day') {
|
|
|
- return `${index}:00`;
|
|
|
- }
|
|
|
- return `第${index + 1}${this.currentView === 'week' ? '天' : '日'}`;
|
|
|
+ formatTime(timeStamp) {
|
|
|
+ return moment(timeStamp).format('HH:mm')
|
|
|
},
|
|
|
|
|
|
initCharts() {
|
|
|
this.visibleCharts.forEach(chart => {
|
|
|
- const chartDom = document.getElementById(`chart${chart.id}`);
|
|
|
- if (!chartDom) return;
|
|
|
-
|
|
|
- const myChart = echarts.init(chartDom);
|
|
|
- const option = this.getChartOption(chart);
|
|
|
- myChart.setOption(option);
|
|
|
- chart.instance = myChart;
|
|
|
- });
|
|
|
+ const chartDom = document.getElementById(`chart${chart.id}`)
|
|
|
+ if (!chartDom) return
|
|
|
+ const myChart = echarts.init(chartDom)
|
|
|
+ const option = this.getChartOption(chart)
|
|
|
+ myChart.setOption(option)
|
|
|
+ chart.instance = myChart
|
|
|
+ })
|
|
|
},
|
|
|
|
|
|
getChartOption(chart) {
|
|
|
@@ -164,11 +328,11 @@ export default {
|
|
|
},
|
|
|
xAxis: {
|
|
|
type: 'category',
|
|
|
- data: Array.from({ length: this.getDataLength() }, (_, i) =>
|
|
|
- this.formatTime(i)
|
|
|
- ),
|
|
|
- axisLabel: { rotate: 45, color: '#666' },
|
|
|
- axisLine: { lineStyle: { color: '#999' } }
|
|
|
+ data: chart.timeStamps, // 使用实际时间序列
|
|
|
+ axisLabel: {
|
|
|
+ rotate: 45,
|
|
|
+ formatter: value => moment(value).format('HH:mm')
|
|
|
+ }
|
|
|
},
|
|
|
yAxis: {
|
|
|
type: 'value',
|
|
|
@@ -192,10 +356,11 @@ export default {
|
|
|
color: '#fff'
|
|
|
}
|
|
|
},
|
|
|
- formatter: (params) => {
|
|
|
+ formatter: params => {
|
|
|
const time = params[0].name
|
|
|
const value = params[0].value
|
|
|
- const riskLevel = this.getRiskLevel(value)
|
|
|
+ const riskLevel = '低'
|
|
|
+ //this.getRiskLevel(value)
|
|
|
return `
|
|
|
<div class="custom-tooltip">
|
|
|
<div class="time">${time}</div>
|
|
|
@@ -211,89 +376,137 @@ export default {
|
|
|
`
|
|
|
}
|
|
|
},
|
|
|
- series: [{
|
|
|
- type: 'line',
|
|
|
- data: chart.data,
|
|
|
- smooth: true,
|
|
|
- lineStyle: { width: 2, color: '#5470C6' },
|
|
|
- areaStyle: {
|
|
|
- color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
|
|
- { offset: 0, color: 'rgba(84, 112, 198, 0.3)' },
|
|
|
- { offset: 1, color: 'rgba(84, 112, 198, 0.05)' }
|
|
|
- ])
|
|
|
+ series: [
|
|
|
+ {
|
|
|
+ type: 'line',
|
|
|
+ data: chart.data,
|
|
|
+ smooth: true,
|
|
|
+ lineStyle: { width: 2, color: '#5470C6' },
|
|
|
+ areaStyle: {
|
|
|
+ color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
|
|
+ { offset: 0, color: 'rgba(84, 112, 198, 0.3)' },
|
|
|
+ { offset: 1, color: 'rgba(84, 112, 198, 0.05)' }
|
|
|
+ ])
|
|
|
+ }
|
|
|
}
|
|
|
- }]
|
|
|
- };
|
|
|
+ ]
|
|
|
+ }
|
|
|
},
|
|
|
|
|
|
toggleTable(index) {
|
|
|
- this.$set(this.showTables, index, !this.showTables[index]);
|
|
|
+ this.$set(this.showTables, index, !this.showTables[index])
|
|
|
this.$nextTick(() => {
|
|
|
this.visibleCharts.forEach(chart => {
|
|
|
- chart.instance.resize();
|
|
|
- });
|
|
|
- });
|
|
|
+ chart.instance.resize()
|
|
|
+ })
|
|
|
+ })
|
|
|
},
|
|
|
|
|
|
changeView(view) {
|
|
|
- this.currentView = view;
|
|
|
- this.generateChartData();
|
|
|
+ this.currentView = view
|
|
|
+
|
|
|
this.$nextTick(() => {
|
|
|
- this.initCharts();
|
|
|
- });
|
|
|
+ this.loadChartData()
|
|
|
+ })
|
|
|
},
|
|
|
|
|
|
getStatusClass(value) {
|
|
|
- if (value > 80) return 'status-high';
|
|
|
- if (value > 50) return 'status-medium';
|
|
|
- return 'status-low';
|
|
|
+ if (value > 80) return 'status-high'
|
|
|
+ if (value > 50) return 'status-medium'
|
|
|
+ return 'status-low'
|
|
|
},
|
|
|
|
|
|
getStatusText(value) {
|
|
|
- if (value > 80) return '高风险';
|
|
|
- if (value > 50) return '中风险';
|
|
|
- return '低风险';
|
|
|
+ if (value > 80) return '高风险'
|
|
|
+ if (value > 50) return '中风险'
|
|
|
+ return '低风险'
|
|
|
},
|
|
|
|
|
|
- handleScroll: throttle(function () {
|
|
|
- const container = this.$refs.container;
|
|
|
- if (!container) return;
|
|
|
+ handleScroll: throttle(function() {
|
|
|
+ const container = this.$refs.container
|
|
|
+ if (!container) return
|
|
|
|
|
|
- const { scrollTop, scrollHeight, clientHeight } = container;
|
|
|
+ const { scrollTop, scrollHeight, clientHeight } = container
|
|
|
if (scrollHeight - (scrollTop + clientHeight) < 100 && !this.loading) {
|
|
|
- this.loadMore();
|
|
|
+ this.loadMore()
|
|
|
}
|
|
|
}, 200),
|
|
|
|
|
|
loadMore() {
|
|
|
- this.loading = true;
|
|
|
+ this.loading = true
|
|
|
setTimeout(() => {
|
|
|
- const nextPage = this.currentPage + 1;
|
|
|
- const start = this.currentPage * this.pageSize;
|
|
|
- const newCharts = this.allCharts.slice(start, start + this.pageSize);
|
|
|
+ const nextPage = this.currentPage + 1
|
|
|
+ const start = this.currentPage * this.pageSize
|
|
|
+ const newCharts = this.allCharts.slice(start, start + this.pageSize)
|
|
|
|
|
|
if (newCharts.length) {
|
|
|
- this.visibleCharts = [...this.visibleCharts, ...newCharts];
|
|
|
- this.showTables = [...this.showTables, ...new Array(newCharts.length).fill(false)];
|
|
|
+ this.visibleCharts = [...this.visibleCharts, ...newCharts]
|
|
|
+ this.showTables = [...this.showTables, ...new Array(newCharts.length).fill(false)]
|
|
|
this.$nextTick(() => {
|
|
|
- this.initCharts();
|
|
|
- this.currentPage = nextPage;
|
|
|
- });
|
|
|
+ this.initCharts()
|
|
|
+ this.currentPage = nextPage
|
|
|
+ })
|
|
|
}
|
|
|
- this.loading = false;
|
|
|
- }, 1000);
|
|
|
+ this.loading = false
|
|
|
+ }, 1000)
|
|
|
},
|
|
|
|
|
|
handleResize() {
|
|
|
this.visibleCharts.forEach(chart => {
|
|
|
- chart.instance.resize();
|
|
|
- });
|
|
|
+ chart.instance.resize()
|
|
|
+ })
|
|
|
}
|
|
|
}
|
|
|
-};
|
|
|
+}
|
|
|
</script>
|
|
|
|
|
|
<style lang="less" scoped>
|
|
|
+.info-row {
|
|
|
+ background: rgba(242, 245, 247, 0.9);
|
|
|
+ padding: 16px;
|
|
|
+ border-radius: 8px;
|
|
|
+ margin-bottom: 20px;
|
|
|
+ display: flex;
|
|
|
+ gap: 30px;
|
|
|
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
|
+}
|
|
|
+
|
|
|
+.info-item {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ font-size: 16px;
|
|
|
+
|
|
|
+ label {
|
|
|
+ color: #666;
|
|
|
+ margin-right: 8px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .highlight {
|
|
|
+ color: #2d8cf0;
|
|
|
+ font-weight: 500;
|
|
|
+ }
|
|
|
+
|
|
|
+ .risk-status {
|
|
|
+ display: flex;
|
|
|
+ gap: 15px;
|
|
|
+
|
|
|
+ .risk-item {
|
|
|
+ padding: 4px 8px;
|
|
|
+ border-radius: 4px;
|
|
|
+ background-color: rgba(255, 255, 255, 0.9);
|
|
|
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+.filter-row {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ margin-bottom: 20px;
|
|
|
+ padding: 12px 16px;
|
|
|
+ background: #fff;
|
|
|
+ border-radius: 8px;
|
|
|
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
|
+}
|
|
|
.head {
|
|
|
display: flex;
|
|
|
gap: 15px;
|
|
|
@@ -488,4 +701,4 @@ th {
|
|
|
background: rgba(82, 196, 26, 0.1);
|
|
|
border: 1px solid rgba(82, 196, 26, 0.3);
|
|
|
}
|
|
|
-</style>
|
|
|
+</style>
|