|
@@ -84,17 +84,18 @@
|
|
|
<span class="text-base font-medium " style="color: #b6c8da">{{t('stat.deviceStatus')}}</span>
|
|
<span class="text-base font-medium " style="color: #b6c8da">{{t('stat.deviceStatus')}}</span>
|
|
|
</div>
|
|
</div>
|
|
|
</template>
|
|
</template>
|
|
|
- <div style="display:flex; align-items:center;min-height: 292px;">
|
|
|
|
|
- <div ref="statusChartRef" style="width:100%; max-width:250px; height:250px;"></div>
|
|
|
|
|
- <div class="text-[12px]" style="width:100%; display:flex; flex-wrap:wrap; justify-content:center; gap:8px; color:#fff;margin-top: -50px;">
|
|
|
|
|
- <div v-for="item in legendData" :key="item.name" style="display:flex; align-items:center; gap:12px; padding:0; min-width:160px; justify-content:space-between;">
|
|
|
|
|
- <div style="display:flex; align-items:center; gap:8px;">
|
|
|
|
|
- <span :style="{display:'inline-block', width:'12px', height:'12px', 'border-radius':'50%', background:item.color}"></span>
|
|
|
|
|
- <span>{{ item.name }}</span>
|
|
|
|
|
|
|
+ <div style="display:flex; align-items:center; justify-content: center; min-height: 290px; flex-direction:column; gap:6px;">
|
|
|
|
|
+ <div ref="statusChartRef" style="width:100%; max-width:200px; height:170px;"></div>
|
|
|
|
|
+ <div class="text-[12px] h-[100px] w-[90%] flex flex-col justify-between items-center">
|
|
|
|
|
+ <div v-for="item in legendData" :key="item.name" class="flex">
|
|
|
|
|
+ <div class="flex items-center gap-1">
|
|
|
|
|
+ <span class="status-legend-color" :style="{background: item.color}"></span>
|
|
|
|
|
+ <span class="w-[100px] text-[#fff]">{{ item.name }}</span>
|
|
|
|
|
+
|
|
|
</div>
|
|
</div>
|
|
|
- <div style="display:flex; align-items:center; gap:10px; color:#fff;">
|
|
|
|
|
- <span style="font-weight:700">{{ item.value }} 台</span>
|
|
|
|
|
- <span>{{ item.percent }}%</span>
|
|
|
|
|
|
|
+ <div class="flex items-center">
|
|
|
|
|
+ <span class="text-[#fff] text-right w-12">{{ item.value }} 台</span>
|
|
|
|
|
+ <span class="status-legend-percent text-right w-14">{{ item.percent }}%</span>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
@@ -113,8 +114,8 @@
|
|
|
:data="projectData"
|
|
:data="projectData"
|
|
|
border
|
|
border
|
|
|
@row-click="projectDataRowClick"
|
|
@row-click="projectDataRowClick"
|
|
|
- :header-cell-style="{color:'#fff'}"
|
|
|
|
|
- :cell-style="{ color: '#fff', height: '65px' }"
|
|
|
|
|
|
|
+ :header-cell-style="{color:'#fff', 'background-color':'transparent',height:'58px'}"
|
|
|
|
|
+ :cell-style="{ color: '#fff', height: '58px' }"
|
|
|
style="width:100%"
|
|
style="width:100%"
|
|
|
|
|
|
|
|
>
|
|
>
|
|
@@ -142,7 +143,7 @@
|
|
|
|
|
|
|
|
<el-row :gutter="16" class="mb-4">
|
|
<el-row :gutter="16" class="mb-4">
|
|
|
<!-- 备件更换情况部分保持不变 -->
|
|
<!-- 备件更换情况部分保持不变 -->
|
|
|
- <el-col :span="10" :xs="24">
|
|
|
|
|
|
|
+ <el-col :span="12" :xs="24">
|
|
|
<el-card class="chart-card" shadow="never">
|
|
<el-card class="chart-card" shadow="never">
|
|
|
<template #header>
|
|
<template #header>
|
|
|
<div style="display: flex; flex-direction: row; justify-content: space-between">
|
|
<div style="display: flex; flex-direction: row; justify-content: space-between">
|
|
@@ -195,8 +196,9 @@
|
|
|
@row-click="handleRowClick"
|
|
@row-click="handleRowClick"
|
|
|
style="width: 100%; color: #4c4c4c;"
|
|
style="width: 100%; color: #4c4c4c;"
|
|
|
:header-cell-style="{
|
|
:header-cell-style="{
|
|
|
- 'background-color': '#2196df',
|
|
|
|
|
|
|
+ 'background-color': 'transparent',
|
|
|
'color': 'white',
|
|
'color': 'white',
|
|
|
|
|
+ 'height':'56px',
|
|
|
'border-color': '#457794'
|
|
'border-color': '#457794'
|
|
|
}"
|
|
}"
|
|
|
:cell-style="{
|
|
:cell-style="{
|
|
@@ -236,7 +238,7 @@
|
|
|
</el-card>
|
|
</el-card>
|
|
|
</el-col>
|
|
</el-col>
|
|
|
<!-- 月度工作量表 -->
|
|
<!-- 月度工作量表 -->
|
|
|
- <el-col :span="14" :xs="24">
|
|
|
|
|
|
|
+ <el-col :span="12" :xs="24">
|
|
|
<el-card class="chart-card" shadow="never">
|
|
<el-card class="chart-card" shadow="never">
|
|
|
<template #header>
|
|
<template #header>
|
|
|
<div class="flex items-center justify-between">
|
|
<div class="flex items-center justify-between">
|
|
@@ -250,32 +252,32 @@
|
|
|
height="420px"
|
|
height="420px"
|
|
|
:disabled-affix="true"
|
|
:disabled-affix="true"
|
|
|
style="width:100%"
|
|
style="width:100%"
|
|
|
- :header-cell-style="{color:'#fff'}"
|
|
|
|
|
|
|
+ :header-cell-style="{color:'#fff', 'background-color':'transparent'}"
|
|
|
:cell-style="{ color: '#fff' }"
|
|
:cell-style="{ color: '#fff' }"
|
|
|
:summary-method="tableSummary"
|
|
:summary-method="tableSummary"
|
|
|
|
|
|
|
|
show-summary>
|
|
show-summary>
|
|
|
- <el-table-column prop="month" label="月份" width="80" fixed="left" align="center" />
|
|
|
|
|
|
|
+ <el-table-column prop="month" label="月份" width="50" fixed="left" align="center" />
|
|
|
|
|
|
|
|
<el-table-column label="2025年" align="center">
|
|
<el-table-column label="2025年" align="center">
|
|
|
- <el-table-column prop="y2025_fractures" label="压裂井数" align="center" width="110" />
|
|
|
|
|
- <el-table-column prop="y2025_layers" label="压裂层数" width="110" align="center" />
|
|
|
|
|
- <el-table-column prop="y2025_pump_trips" label="泵车台次" width="110" align="center" />
|
|
|
|
|
- <el-table-column prop="y2025_oil_wells" label="连油井数" width="110" align="center" />
|
|
|
|
|
|
|
+ <el-table-column prop="y2025_fractures" label="压裂井数" align="center" min-width="50" />
|
|
|
|
|
+ <el-table-column prop="y2025_layers" label="压裂层数" min-width="50" align="center" />
|
|
|
|
|
+ <el-table-column prop="y2025_pump_trips" label="泵车台次" min-width="50" align="center" />
|
|
|
|
|
+ <el-table-column prop="y2025_oil_wells" label="连油井数" min-width="50" align="center" />
|
|
|
</el-table-column>
|
|
</el-table-column>
|
|
|
|
|
|
|
|
<el-table-column label="2024年" align="center">
|
|
<el-table-column label="2024年" align="center">
|
|
|
- <el-table-column prop="y2024_fractures" label="压裂井数" width="110" align="center" />
|
|
|
|
|
- <el-table-column prop="y2024_layers" label="压裂层数" width="110" align="center" />
|
|
|
|
|
- <el-table-column prop="y2024_pump_trips" label="泵车台次" width="110" align="center" />
|
|
|
|
|
- <el-table-column prop="y2024_oil_wells" label="连油井数" width="110" align="center" />
|
|
|
|
|
|
|
+ <el-table-column prop="y2024_fractures" label="压裂井数" min-width="50" align="center" />
|
|
|
|
|
+ <el-table-column prop="y2024_layers" label="压裂层数" min-width="50" align="center" />
|
|
|
|
|
+ <el-table-column prop="y2024_pump_trips" label="泵车台次" min-width="50" align="center" />
|
|
|
|
|
+ <el-table-column prop="y2024_oil_wells" label="连油井数" min-width="50" align="center" />
|
|
|
</el-table-column>
|
|
</el-table-column>
|
|
|
|
|
|
|
|
<el-table-column label="同比增长量" align="center">
|
|
<el-table-column label="同比增长量" align="center">
|
|
|
- <el-table-column prop="diff_fractures" label="压裂井数" width="110" align="center" />
|
|
|
|
|
- <el-table-column prop="diff_layers" label="压裂层数" width="110" align="center" />
|
|
|
|
|
- <el-table-column prop="diff_pump_trips" label="泵车台次" width="110" align="center" />
|
|
|
|
|
- <el-table-column prop="diff_oil_wells" label="连油井数" width="110" align="center" />
|
|
|
|
|
|
|
+ <el-table-column prop="diff_fractures" label="压裂井数" min-width="50" align="center" />
|
|
|
|
|
+ <el-table-column prop="diff_layers" label="压裂层数" min-width="50" align="center" />
|
|
|
|
|
+ <el-table-column prop="diff_pump_trips" label="泵车台次" min-width="50" align="center" />
|
|
|
|
|
+ <el-table-column prop="diff_oil_wells" label="连油井数" min-width="50" align="center" />
|
|
|
</el-table-column>
|
|
</el-table-column>
|
|
|
</el-table>
|
|
</el-table>
|
|
|
</div>
|
|
</div>
|
|
@@ -297,7 +299,7 @@
|
|
|
border
|
|
border
|
|
|
style="width: 100%;"
|
|
style="width: 100%;"
|
|
|
:header-cell-style="{
|
|
:header-cell-style="{
|
|
|
- 'background-color': 'rgba(0, 0, 0, 0.2)',
|
|
|
|
|
|
|
+ 'background-color': 'transparent',
|
|
|
'color': 'black',
|
|
'color': 'black',
|
|
|
'border-color': '#457794'
|
|
'border-color': '#457794'
|
|
|
}"
|
|
}"
|
|
@@ -349,7 +351,7 @@
|
|
|
<el-table
|
|
<el-table
|
|
|
:data="domesticData"
|
|
:data="domesticData"
|
|
|
border
|
|
border
|
|
|
- :header-cell-style="{color:'#fff'}"
|
|
|
|
|
|
|
+ :header-cell-style="{color:'#fff', 'background-color':'transparent'}"
|
|
|
:cell-style="{ color: '#fff' }"
|
|
:cell-style="{ color: '#fff' }"
|
|
|
style="width:100%"
|
|
style="width:100%"
|
|
|
:summary-method="tableSummary"
|
|
:summary-method="tableSummary"
|
|
@@ -383,7 +385,7 @@
|
|
|
<el-table
|
|
<el-table
|
|
|
:data="iraqTableData"
|
|
:data="iraqTableData"
|
|
|
border
|
|
border
|
|
|
- :header-cell-style="{color:'#fff'}"
|
|
|
|
|
|
|
+ :header-cell-style="{color:'#fff', 'background-color':'transparent'}"
|
|
|
:cell-style="{ color: '#fff' }"
|
|
:cell-style="{ color: '#fff' }"
|
|
|
style="width:100%"
|
|
style="width:100%"
|
|
|
|
|
|
|
@@ -418,7 +420,7 @@
|
|
|
<el-table
|
|
<el-table
|
|
|
:data="libyaTableData"
|
|
:data="libyaTableData"
|
|
|
border
|
|
border
|
|
|
- :header-cell-style="{color:'#fff'}"
|
|
|
|
|
|
|
+ :header-cell-style="{color:'#fff', 'background-color':'transparent'}"
|
|
|
:cell-style="{ color: '#fff' }"
|
|
:cell-style="{ color: '#fff' }"
|
|
|
:row-class-name="tableRowClass"
|
|
:row-class-name="tableRowClass"
|
|
|
style="width:100%"
|
|
style="width:100%"
|
|
@@ -534,8 +536,23 @@ const typeData = ref([])
|
|
|
// 配色(与图表保持一致)
|
|
// 配色(与图表保持一致)
|
|
|
const statusColors = ['#2ed3df', '#34d399', '#ff6b95', '#4aa3ff', '#f59e0b', '#ef4444', '#7dd3fc']
|
|
const statusColors = ['#2ed3df', '#34d399', '#ff6b95', '#4aa3ff', '#f59e0b', '#ef4444', '#7dd3fc']
|
|
|
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * 将后端返回的多种可能结构规范化为数组形式:
|
|
|
|
|
+ * - 如果已经是数组则直接使用
|
|
|
|
|
+ * - 如果包含 data 或 series 字段且为数组则优先使用
|
|
|
|
|
+ * - 否则把对象的键值对转换为 {name, value} 数组
|
|
|
|
|
+ */
|
|
|
|
|
+const normalizeTypeData = (val) => {
|
|
|
|
|
+ if (Array.isArray(val)) return val
|
|
|
|
|
+ if (!val || typeof val !== 'object') return []
|
|
|
|
|
+ if (Array.isArray(val.data)) return val.data
|
|
|
|
|
+ if (Array.isArray(val.series)) return val.series
|
|
|
|
|
+ // plain object with keys -> map to array
|
|
|
|
|
+ return Object.keys(val).map((k) => ({ name: k, value: val[k] }))
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
const legendData = computed(() => {
|
|
const legendData = computed(() => {
|
|
|
- const arr = Array.isArray(typeData.value) ? typeData.value : []
|
|
|
|
|
|
|
+ const arr = normalizeTypeData(typeData.value)
|
|
|
const total = arr.reduce((s, it) => s + (Number(it.value) || 0), 0)
|
|
const total = arr.reduce((s, it) => s + (Number(it.value) || 0), 0)
|
|
|
return arr.map((it, idx) => ({
|
|
return arr.map((it, idx) => ({
|
|
|
name: it.name,
|
|
name: it.name,
|
|
@@ -1036,7 +1053,7 @@ const initDeviceStatusCharts = () => {
|
|
|
// ignore
|
|
// ignore
|
|
|
}
|
|
}
|
|
|
statusChartInstance = echarts.init(statusChartRef.value)
|
|
statusChartInstance = echarts.init(statusChartRef.value)
|
|
|
- const data = Array.isArray(typeData.value) ? typeData.value : []
|
|
|
|
|
|
|
+ const data = normalizeTypeData(typeData.value)
|
|
|
const option = {
|
|
const option = {
|
|
|
color: statusColors,
|
|
color: statusColors,
|
|
|
tooltip: {
|
|
tooltip: {
|
|
@@ -1047,8 +1064,8 @@ const initDeviceStatusCharts = () => {
|
|
|
{
|
|
{
|
|
|
name: '',
|
|
name: '',
|
|
|
type: 'pie',
|
|
type: 'pie',
|
|
|
- radius: ['45%', '65%'],
|
|
|
|
|
- center: ['50%', '36%'],
|
|
|
|
|
|
|
+ radius: ['38%', '58%'],
|
|
|
|
|
+ center: ['50%', '30%'],
|
|
|
avoidLabelOverlap: false,
|
|
avoidLabelOverlap: false,
|
|
|
label: { show: false },
|
|
label: { show: false },
|
|
|
labelLine: { show: false },
|
|
labelLine: { show: false },
|
|
@@ -1229,21 +1246,11 @@ onMounted(async () => {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
-::v-deep .el-table th {
|
|
|
|
|
- background-color: #2196df !important;
|
|
|
|
|
-}
|
|
|
|
|
|
|
|
|
|
::v-deep .el-table__footer {
|
|
::v-deep .el-table__footer {
|
|
|
color: #fff !important;
|
|
color: #fff !important;
|
|
|
}
|
|
}
|
|
|
-::v-deep .el-table__footer-wrapper {
|
|
|
|
|
- color: #fff !important;
|
|
|
|
|
- background-color: #42c5f9 !important;
|
|
|
|
|
-}
|
|
|
|
|
|
|
|
|
|
-::v-deep th.el-table-fixed-column--left {
|
|
|
|
|
- background-color: #3fc1f7 !important;
|
|
|
|
|
-}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -1251,9 +1258,7 @@ onMounted(async () => {
|
|
|
color: #fff !important;
|
|
color: #fff !important;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-::v-deep td.el-table-fixed-column--left {
|
|
|
|
|
- background-color: #3fc1f7 !important;
|
|
|
|
|
-}
|
|
|
|
|
|
|
+
|
|
|
|
|
|
|
|
.summary {
|
|
.summary {
|
|
|
.el-col {
|
|
.el-col {
|
|
@@ -1385,4 +1390,44 @@ onMounted(async () => {
|
|
|
.custom-table :deep .el-table__row {
|
|
.custom-table :deep .el-table__row {
|
|
|
height: 50px !important; /* 高度根据需求调整 */
|
|
height: 50px !important; /* 高度根据需求调整 */
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+/* 设备状态图例自适应样式 */
|
|
|
|
|
+.status-legend {
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ flex-wrap: wrap;
|
|
|
|
|
+ justify-content: center;
|
|
|
|
|
+ gap: 8px;
|
|
|
|
|
+ padding: 6px 0;
|
|
|
|
|
+ box-sizing: border-box;
|
|
|
|
|
+ max-height: 90px; /* 限制高度,超出显示滚动 */
|
|
|
|
|
+ overflow-y: auto;
|
|
|
|
|
+}
|
|
|
|
|
+.status-legend-item {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ justify-content: space-between;
|
|
|
|
|
+ gap: 12px;
|
|
|
|
|
+ padding: 6px 10px;
|
|
|
|
|
+ min-width: 120px;
|
|
|
|
|
+ max-width: 100%;
|
|
|
|
|
+ box-sizing: border-box;
|
|
|
|
|
+}
|
|
|
|
|
+.status-legend-left { display:flex; align-items:center; gap:8px; min-width:0; }
|
|
|
|
|
+.status-legend-color { display:inline-block; width:12px; height:12px; border-radius:50%; flex:0 0 12px; }
|
|
|
|
|
+.status-legend-name {
|
|
|
|
|
+ max-width: calc(100% - 60px);
|
|
|
|
|
+ overflow: hidden;
|
|
|
|
|
+ text-overflow: ellipsis;
|
|
|
|
|
+ white-space: nowrap;
|
|
|
|
|
+ color: #fff;
|
|
|
|
|
+}
|
|
|
|
|
+.status-legend-right { display:flex; align-items:center; gap:8px; flex-shrink:0; }
|
|
|
|
|
+.status-legend-value { font-weight:700; color:#fff; }
|
|
|
|
|
+.status-legend-percent { color:#fff; }
|
|
|
|
|
+
|
|
|
|
|
+@media (max-width: 520px) {
|
|
|
|
|
+ .status-legend-item { min-width: 100%; }
|
|
|
|
|
+ .status-legend { justify-content: flex-start; max-height: none; overflow: visible; }
|
|
|
|
|
+}
|
|
|
</style>
|
|
</style>
|