Compare commits
No commits in common. '1aad86f8cb9d6c0f0d40e15181785d2cdb251973' and 'dcde3b475ab0f5e3f54ae41dd34b950c41b437c6' have entirely different histories.
1aad86f8cb
...
dcde3b475a
@ -1,770 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="energy-overview-page">
|
|
||||||
<ContentWrap>
|
|
||||||
<el-form
|
|
||||||
ref="queryFormRef"
|
|
||||||
class="-mb-15px energy-overview-filter"
|
|
||||||
:model="queryParams"
|
|
||||||
:inline="true"
|
|
||||||
label-width="auto"
|
|
||||||
>
|
|
||||||
<el-form-item label="所属区域" prop="orgId">
|
|
||||||
<el-select v-model="queryParams.orgId" clearable filterable placeholder="请选择所属区域" class="!w-220px">
|
|
||||||
<el-option v-for="item in orgOptions" :key="item.value" :label="item.label" :value="item.value" />
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="能源类型" prop="energyTypeId">
|
|
||||||
<el-select
|
|
||||||
v-model="queryParams.energyTypeId"
|
|
||||||
:disabled="!hasEnergyTypes"
|
|
||||||
placeholder="请选择能源类型"
|
|
||||||
class="!w-220px"
|
|
||||||
>
|
|
||||||
<el-option v-for="item in energyTypeOptions" :key="item.id" :label="item.name" :value="item.id" />
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="时间范围" prop="timeRange">
|
|
||||||
<el-date-picker
|
|
||||||
v-model="queryParams.timeRange"
|
|
||||||
type="datetimerange"
|
|
||||||
value-format="YYYY-MM-DD HH:mm:ss"
|
|
||||||
format="YYYY-MM-DD HH:mm:ss"
|
|
||||||
start-placeholder="开始时间"
|
|
||||||
end-placeholder="结束时间"
|
|
||||||
range-separator="~"
|
|
||||||
:default-time="[new Date('2000-01-01 00:00:00'), new Date('2000-01-01 23:59:59')]"
|
|
||||||
class="!w-420px"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item>
|
|
||||||
<el-button type="primary" @click="handleQuery">
|
|
||||||
<Icon icon="ep:search" class="mr-5px" />
|
|
||||||
查询
|
|
||||||
</el-button>
|
|
||||||
<el-button @click="resetQuery">
|
|
||||||
<Icon icon="ep:refresh" class="mr-5px" />
|
|
||||||
重置
|
|
||||||
</el-button>
|
|
||||||
<el-button type="success" plain @click="handleExport">
|
|
||||||
<Icon icon="ep:download" class="mr-5px" />
|
|
||||||
导出
|
|
||||||
</el-button>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
</ContentWrap>
|
|
||||||
|
|
||||||
<template v-if="hasEnergyTypes">
|
|
||||||
<div class="metric-grid">
|
|
||||||
<div v-for="item in metricCards" :key="item.key" class="metric-card">
|
|
||||||
<div class="metric-icon" :class="item.theme">
|
|
||||||
<Icon :icon="item.icon" />
|
|
||||||
</div>
|
|
||||||
<div class="metric-content">
|
|
||||||
<div class="metric-label">{{ item.label }}</div>
|
|
||||||
<div class="metric-value">
|
|
||||||
{{ item.value }}
|
|
||||||
<span class="metric-unit">{{ item.unit }}</span>
|
|
||||||
</div>
|
|
||||||
<div class="metric-sub">
|
|
||||||
<span>{{ item.subLabel }}</span>
|
|
||||||
<span v-if="item.change" class="metric-change" :class="{ down: item.down }">
|
|
||||||
<Icon :icon="item.down ? 'ep:bottom' : 'ep:top'" />
|
|
||||||
{{ item.change }}
|
|
||||||
</span>
|
|
||||||
<span v-else>{{ item.subValue }}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<el-row :gutter="12" class="chart-row">
|
|
||||||
<el-col :xl="12" :lg="12" :md="24" :sm="24" :xs="24">
|
|
||||||
<ContentWrap class="overview-panel">
|
|
||||||
<div class="panel-header">
|
|
||||||
<div class="panel-title">
|
|
||||||
能源用量趋势
|
|
||||||
<Icon icon="ep:info-filled" class="panel-info" />
|
|
||||||
</div>
|
|
||||||
<div class="panel-actions">
|
|
||||||
<el-button text type="primary">
|
|
||||||
<Icon icon="ep:trend-charts" />
|
|
||||||
</el-button>
|
|
||||||
<el-button text type="primary">
|
|
||||||
<Icon icon="ep:download" />
|
|
||||||
</el-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<Echart :height="300" :options="trendChartOptions" />
|
|
||||||
</ContentWrap>
|
|
||||||
</el-col>
|
|
||||||
<el-col :xl="12" :lg="12" :md="24" :sm="24" :xs="24">
|
|
||||||
<ContentWrap class="overview-panel">
|
|
||||||
<div class="panel-header">
|
|
||||||
<div class="panel-title">
|
|
||||||
区域能耗占比
|
|
||||||
<Icon icon="ep:info-filled" class="panel-info" />
|
|
||||||
</div>
|
|
||||||
<div class="panel-actions">
|
|
||||||
<el-button text type="primary">
|
|
||||||
<Icon icon="ep:pie-chart" />
|
|
||||||
</el-button>
|
|
||||||
<el-button text type="primary">
|
|
||||||
<Icon icon="ep:download" />
|
|
||||||
</el-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<Echart :height="300" :options="regionPieOptions" />
|
|
||||||
</ContentWrap>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
|
|
||||||
<el-row :gutter="12" class="detail-row">
|
|
||||||
<el-col :xl="7" :lg="8" :md="24" :sm="24" :xs="24">
|
|
||||||
<ContentWrap class="overview-panel">
|
|
||||||
<div class="panel-header">
|
|
||||||
<div class="panel-title">
|
|
||||||
能耗排行 TOP5
|
|
||||||
<Icon icon="ep:info-filled" class="panel-info" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<el-table :data="rankList" :stripe="true" :show-overflow-tooltip="true">
|
|
||||||
<el-table-column label="排名" align="center" width="70">
|
|
||||||
<template #default="scope">
|
|
||||||
<span class="rank-index" :class="`rank-${scope.$index + 1}`">{{ scope.$index + 1 }}</span>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="名称" prop="name" min-width="150" />
|
|
||||||
<el-table-column label="所属区域" prop="region" width="110" />
|
|
||||||
<el-table-column :label="`用量 (${selectedEnergyUnit})`" prop="value" align="right" width="120" />
|
|
||||||
</el-table>
|
|
||||||
</ContentWrap>
|
|
||||||
</el-col>
|
|
||||||
<el-col :xl="17" :lg="16" :md="24" :sm="24" :xs="24">
|
|
||||||
<ContentWrap class="overview-panel">
|
|
||||||
<div class="panel-header">
|
|
||||||
<div class="panel-title">
|
|
||||||
能源明细表
|
|
||||||
<Icon icon="ep:info-filled" class="panel-info" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<el-table v-loading="loading" :data="pageDetailList" :stripe="true" :show-overflow-tooltip="true">
|
|
||||||
<el-table-column label="表名称" prop="name" min-width="170" />
|
|
||||||
<el-table-column label="能源类型" prop="energyType" align="center" width="100" />
|
|
||||||
<el-table-column label="所属区域" prop="region" align="center" width="120" />
|
|
||||||
<el-table-column :label="`能源用量 (${selectedEnergyUnit})`" prop="value" align="right" width="150" />
|
|
||||||
<el-table-column label="开始时间" prop="startTime" align="center" width="180" />
|
|
||||||
<el-table-column label="结束时间" prop="endTime" align="center" width="180" />
|
|
||||||
</el-table>
|
|
||||||
<Pagination
|
|
||||||
:total="total"
|
|
||||||
v-model:page="queryParams.pageNo"
|
|
||||||
v-model:limit="queryParams.pageSize"
|
|
||||||
@pagination="getList"
|
|
||||||
/>
|
|
||||||
</ContentWrap>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<ContentWrap v-else class="empty-panel">
|
|
||||||
<el-empty description="请先配置能源类型" :image-size="120" />
|
|
||||||
</ContentWrap>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { EChartsOption } from 'echarts'
|
|
||||||
import { Echart } from '@/components/Echart'
|
|
||||||
import { EnergyTypeApi, EnergyTypeVO } from '@/api/mes/energytype'
|
|
||||||
|
|
||||||
defineOptions({ name: 'EnergyOverview' })
|
|
||||||
|
|
||||||
interface MetricCard {
|
|
||||||
key: string
|
|
||||||
label: string
|
|
||||||
value: string
|
|
||||||
unit: string
|
|
||||||
icon: string
|
|
||||||
theme: string
|
|
||||||
subLabel: string
|
|
||||||
change?: string
|
|
||||||
down?: boolean
|
|
||||||
subValue?: string
|
|
||||||
}
|
|
||||||
|
|
||||||
interface DetailRow {
|
|
||||||
id: number
|
|
||||||
name: string
|
|
||||||
energyType: string
|
|
||||||
region: string
|
|
||||||
value: string
|
|
||||||
startTime: string
|
|
||||||
endTime: string
|
|
||||||
}
|
|
||||||
|
|
||||||
const message = useMessage()
|
|
||||||
|
|
||||||
const defaultTimeRange = ['2026-05-04 00:00:00', '2026-05-05 23:59:59']
|
|
||||||
const orgOptions = [
|
|
||||||
{ label: '成型系统', value: 1 },
|
|
||||||
{ label: '蛋托线01', value: 2 },
|
|
||||||
{ label: '烘干系统', value: 3 }
|
|
||||||
]
|
|
||||||
|
|
||||||
const loading = ref(false)
|
|
||||||
const queryFormRef = ref()
|
|
||||||
const energyTypeOptions = ref<EnergyTypeVO[]>([])
|
|
||||||
const defaultEnergyTypeId = ref<number>()
|
|
||||||
const queryParams = reactive({
|
|
||||||
pageNo: 1,
|
|
||||||
pageSize: 10,
|
|
||||||
orgId: undefined as number | undefined,
|
|
||||||
energyTypeId: undefined as number | undefined,
|
|
||||||
timeRange: [...defaultTimeRange]
|
|
||||||
})
|
|
||||||
|
|
||||||
const metricCards = ref<MetricCard[]>([])
|
|
||||||
const rankList = ref([
|
|
||||||
{ name: '蛋托成型柜用电量', region: '成型系统', value: '2,139.09' },
|
|
||||||
{ name: '蛋托线真空柜用电量', region: '蛋托线01', value: '0' },
|
|
||||||
{ name: '蛋托干燥柜用电量', region: '烘干系统', value: '0' },
|
|
||||||
{ name: '蛋托线其它用电量', region: '蛋托线01', value: '0' },
|
|
||||||
{ name: '烘干系统其它用电量', region: '烘干系统', value: '0' }
|
|
||||||
])
|
|
||||||
const detailList = ref<DetailRow[]>([])
|
|
||||||
const pageDetailList = ref<DetailRow[]>([])
|
|
||||||
const total = ref(0)
|
|
||||||
const hasEnergyTypes = computed(() => energyTypeOptions.value.length > 0)
|
|
||||||
const selectedEnergyType = computed(() =>
|
|
||||||
energyTypeOptions.value.find((item) => item.id === queryParams.energyTypeId)
|
|
||||||
)
|
|
||||||
const selectedEnergyName = computed(() => selectedEnergyType.value?.name || '电')
|
|
||||||
const selectedEnergyUnit = computed(() => selectedEnergyType.value?.unit || 'kWh')
|
|
||||||
const selectedUnitConsumptionUnit = computed(() => `${selectedEnergyUnit.value}/件`)
|
|
||||||
|
|
||||||
const hours = [
|
|
||||||
'00:00',
|
|
||||||
'01:00',
|
|
||||||
'02:00',
|
|
||||||
'03:00',
|
|
||||||
'04:00',
|
|
||||||
'05:00',
|
|
||||||
'06:00',
|
|
||||||
'07:00',
|
|
||||||
'08:00',
|
|
||||||
'09:00',
|
|
||||||
'10:00',
|
|
||||||
'11:00',
|
|
||||||
'12:00',
|
|
||||||
'13:00',
|
|
||||||
'14:00',
|
|
||||||
'15:00',
|
|
||||||
'16:00',
|
|
||||||
'17:00',
|
|
||||||
'18:00',
|
|
||||||
'19:00',
|
|
||||||
'20:00',
|
|
||||||
'21:00',
|
|
||||||
'22:00'
|
|
||||||
]
|
|
||||||
const trendData = [90, 80, 72, 75, 74, 85, 105, 116, 120, 112, 123, 127, 122, 146, 156.8, 147, 116, 94, 88, 102, 103, 116, 106]
|
|
||||||
const regionData = [
|
|
||||||
{ name: '成型系统', value: 2139.09 },
|
|
||||||
{ name: '蛋托线01', value: 0 },
|
|
||||||
{ name: '烘干系统', value: 0 }
|
|
||||||
]
|
|
||||||
|
|
||||||
const trendChartOptions = reactive<EChartsOption>({
|
|
||||||
color: ['#2f7df6'],
|
|
||||||
tooltip: {
|
|
||||||
trigger: 'axis',
|
|
||||||
formatter: (params: any) => {
|
|
||||||
const item = params?.[0]
|
|
||||||
return `${item.axisValue}<br />用电量:${item.data} kWh`
|
|
||||||
}
|
|
||||||
},
|
|
||||||
legend: {
|
|
||||||
top: 4,
|
|
||||||
data: ['用电量 (kWh)']
|
|
||||||
},
|
|
||||||
grid: {
|
|
||||||
left: 24,
|
|
||||||
right: 24,
|
|
||||||
top: 46,
|
|
||||||
bottom: 32,
|
|
||||||
containLabel: true
|
|
||||||
},
|
|
||||||
xAxis: {
|
|
||||||
type: 'category',
|
|
||||||
boundaryGap: false,
|
|
||||||
name: '时间(小时)',
|
|
||||||
nameLocation: 'middle',
|
|
||||||
nameGap: 28,
|
|
||||||
data: hours,
|
|
||||||
axisLine: { lineStyle: { color: '#dcdfe6' } },
|
|
||||||
axisLabel: { color: '#606266' }
|
|
||||||
},
|
|
||||||
yAxis: {
|
|
||||||
type: 'value',
|
|
||||||
name: 'kWh',
|
|
||||||
min: 0,
|
|
||||||
max: 180,
|
|
||||||
interval: 30,
|
|
||||||
axisLabel: { color: '#606266' },
|
|
||||||
splitLine: { lineStyle: { color: '#e8edf5' } }
|
|
||||||
},
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
name: '用电量 (kWh)',
|
|
||||||
type: 'line',
|
|
||||||
smooth: true,
|
|
||||||
symbol: 'circle',
|
|
||||||
symbolSize: 7,
|
|
||||||
lineStyle: { width: 3 },
|
|
||||||
areaStyle: {
|
|
||||||
color: {
|
|
||||||
type: 'linear',
|
|
||||||
x: 0,
|
|
||||||
y: 0,
|
|
||||||
x2: 0,
|
|
||||||
y2: 1,
|
|
||||||
colorStops: [
|
|
||||||
{ offset: 0, color: 'rgba(47, 125, 246, 0.28)' },
|
|
||||||
{ offset: 1, color: 'rgba(47, 125, 246, 0.04)' }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data: trendData,
|
|
||||||
markPoint: {
|
|
||||||
symbolSize: 48,
|
|
||||||
label: { color: '#2f7df6', formatter: '{c}' },
|
|
||||||
data: [{ type: 'max', name: '峰值' }]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}) as EChartsOption
|
|
||||||
|
|
||||||
const regionPieOptions = reactive<EChartsOption>({
|
|
||||||
color: ['#2f7df6', '#52c41a', '#faad14'],
|
|
||||||
tooltip: {
|
|
||||||
trigger: 'item',
|
|
||||||
formatter: '{b}<br />{c} kWh ({d}%)'
|
|
||||||
},
|
|
||||||
legend: {
|
|
||||||
orient: 'vertical',
|
|
||||||
right: 24,
|
|
||||||
top: 'center',
|
|
||||||
itemWidth: 12,
|
|
||||||
itemHeight: 12,
|
|
||||||
formatter: (name: string) => {
|
|
||||||
const item = regionData.find((row) => row.name === name)
|
|
||||||
const value = item?.value ?? 0
|
|
||||||
const percent = value > 0 ? '100.00' : '0.00'
|
|
||||||
return `${name} ${value.toLocaleString()} kWh (${percent}%)`
|
|
||||||
}
|
|
||||||
},
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
name: '区域能耗',
|
|
||||||
type: 'pie',
|
|
||||||
radius: ['58%', '76%'],
|
|
||||||
center: ['34%', '50%'],
|
|
||||||
avoidLabelOverlap: true,
|
|
||||||
label: {
|
|
||||||
show: true,
|
|
||||||
position: 'center',
|
|
||||||
formatter: '总用电量\n{total|2,139.09 kWh}',
|
|
||||||
color: '#303133',
|
|
||||||
rich: {
|
|
||||||
total: {
|
|
||||||
fontSize: 20,
|
|
||||||
lineHeight: 34,
|
|
||||||
fontWeight: 700,
|
|
||||||
color: '#17233d'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
labelLine: { show: false },
|
|
||||||
data: regionData
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}) as EChartsOption
|
|
||||||
|
|
||||||
const buildMetrics = () => {
|
|
||||||
metricCards.value = [
|
|
||||||
{
|
|
||||||
key: 'total',
|
|
||||||
label: '总用电量',
|
|
||||||
value: '2,139.09',
|
|
||||||
unit: selectedEnergyUnit.value,
|
|
||||||
icon: 'ep:lightning',
|
|
||||||
theme: 'blue',
|
|
||||||
subLabel: '较昨日',
|
|
||||||
change: '12.53%'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'today',
|
|
||||||
label: '今日用电量',
|
|
||||||
value: '860.32',
|
|
||||||
unit: selectedEnergyUnit.value,
|
|
||||||
icon: 'ep:calendar',
|
|
||||||
theme: 'green',
|
|
||||||
subLabel: '较昨日',
|
|
||||||
change: '12.15%'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'peak',
|
|
||||||
label: '峰值用电',
|
|
||||||
value: '156.8',
|
|
||||||
unit: selectedEnergyUnit.value,
|
|
||||||
icon: 'ep:histogram',
|
|
||||||
theme: 'purple',
|
|
||||||
subLabel: '时间:',
|
|
||||||
subValue: '2026-05-04 14:00 ~ 15:00'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'unit',
|
|
||||||
label: '单位产量能耗',
|
|
||||||
value: '0.38',
|
|
||||||
unit: selectedUnitConsumptionUnit.value,
|
|
||||||
icon: 'ep:orange',
|
|
||||||
theme: 'orange',
|
|
||||||
subLabel: '较昨日',
|
|
||||||
change: '5.21%',
|
|
||||||
down: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'region',
|
|
||||||
label: '最大耗能区域',
|
|
||||||
value: '成型系统',
|
|
||||||
unit: '',
|
|
||||||
icon: 'ep:pie-chart',
|
|
||||||
theme: 'cyan',
|
|
||||||
subLabel: '占比:',
|
|
||||||
subValue: '100.00%'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
const buildDetails = () => {
|
|
||||||
const timeRange = queryParams.timeRange?.length === 2 ? queryParams.timeRange : defaultTimeRange
|
|
||||||
detailList.value = [
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
name: '蛋托线真空柜用电量',
|
|
||||||
energyType: selectedEnergyName.value,
|
|
||||||
region: '蛋托线01',
|
|
||||||
value: '0',
|
|
||||||
startTime: timeRange[0],
|
|
||||||
endTime: timeRange[1]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
name: '蛋托成型柜用电量',
|
|
||||||
energyType: selectedEnergyName.value,
|
|
||||||
region: '成型系统',
|
|
||||||
value: '2,139.09',
|
|
||||||
startTime: timeRange[0],
|
|
||||||
endTime: timeRange[1]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 3,
|
|
||||||
name: '蛋托干燥柜用电量',
|
|
||||||
energyType: selectedEnergyName.value,
|
|
||||||
region: '烘干系统',
|
|
||||||
value: '0',
|
|
||||||
startTime: timeRange[0],
|
|
||||||
endTime: timeRange[1]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
total.value = detailList.value.length
|
|
||||||
}
|
|
||||||
|
|
||||||
const getList = () => {
|
|
||||||
if (!hasEnergyTypes.value) {
|
|
||||||
metricCards.value = []
|
|
||||||
detailList.value = []
|
|
||||||
pageDetailList.value = []
|
|
||||||
total.value = 0
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
loading.value = true
|
|
||||||
buildMetrics()
|
|
||||||
buildDetails()
|
|
||||||
const start = (queryParams.pageNo - 1) * queryParams.pageSize
|
|
||||||
pageDetailList.value = detailList.value.slice(start, start + queryParams.pageSize)
|
|
||||||
loading.value = false
|
|
||||||
}
|
|
||||||
|
|
||||||
const normalizeEnergyTypeList = (data: unknown): EnergyTypeVO[] => {
|
|
||||||
const maybeData = data as { data?: EnergyTypeVO[] }
|
|
||||||
if (Array.isArray(data)) {
|
|
||||||
return data as EnergyTypeVO[]
|
|
||||||
}
|
|
||||||
if (Array.isArray(maybeData?.data)) {
|
|
||||||
return maybeData.data
|
|
||||||
}
|
|
||||||
return []
|
|
||||||
}
|
|
||||||
|
|
||||||
const getDefaultEnergyType = (list: EnergyTypeVO[]) => {
|
|
||||||
return (
|
|
||||||
list.find((item) => item.name === '电') ||
|
|
||||||
list.find((item) => item.name === '水') ||
|
|
||||||
list.find((item) => item.name === '气') ||
|
|
||||||
list[0]
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const getEnergyTypes = async () => {
|
|
||||||
try {
|
|
||||||
const data = await EnergyTypeApi.getEnergyTypeList()
|
|
||||||
energyTypeOptions.value = normalizeEnergyTypeList(data)
|
|
||||||
} catch (error) {
|
|
||||||
energyTypeOptions.value = []
|
|
||||||
}
|
|
||||||
|
|
||||||
const defaultEnergyType = getDefaultEnergyType(energyTypeOptions.value)
|
|
||||||
defaultEnergyTypeId.value = defaultEnergyType?.id
|
|
||||||
queryParams.energyTypeId = defaultEnergyType?.id
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleQuery = () => {
|
|
||||||
if (!hasEnergyTypes.value) {
|
|
||||||
getList()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
queryParams.pageNo = 1
|
|
||||||
getList()
|
|
||||||
}
|
|
||||||
|
|
||||||
const resetQuery = () => {
|
|
||||||
queryFormRef.value?.resetFields()
|
|
||||||
queryParams.orgId = undefined
|
|
||||||
queryParams.energyTypeId = defaultEnergyTypeId.value
|
|
||||||
queryParams.timeRange = [...defaultTimeRange]
|
|
||||||
handleQuery()
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleExport = () => {
|
|
||||||
message.info('示例页暂未接入导出接口')
|
|
||||||
}
|
|
||||||
|
|
||||||
onMounted(async () => {
|
|
||||||
await getEnergyTypes()
|
|
||||||
if (hasEnergyTypes.value) {
|
|
||||||
getList()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped lang="scss">
|
|
||||||
.energy-overview-page {
|
|
||||||
.energy-overview-filter {
|
|
||||||
:deep(.el-form-item) {
|
|
||||||
margin-bottom: 15px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.metric-grid {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(5, minmax(180px, 1fr));
|
|
||||||
gap: 12px;
|
|
||||||
margin-bottom: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.metric-card {
|
|
||||||
display: flex;
|
|
||||||
min-height: 118px;
|
|
||||||
padding: 24px 22px;
|
|
||||||
background: var(--el-bg-color);
|
|
||||||
border: 1px solid var(--el-border-color-light);
|
|
||||||
border-radius: 4px;
|
|
||||||
box-shadow: 0 1px 2px rgb(0 0 0 / 3%);
|
|
||||||
align-items: center;
|
|
||||||
gap: 18px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.metric-icon {
|
|
||||||
display: flex;
|
|
||||||
width: 52px;
|
|
||||||
height: 52px;
|
|
||||||
font-size: 28px;
|
|
||||||
color: #fff;
|
|
||||||
border-radius: 50%;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
flex: 0 0 auto;
|
|
||||||
|
|
||||||
&.blue {
|
|
||||||
background: linear-gradient(135deg, #60a5fa, #2563eb);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.green {
|
|
||||||
background: linear-gradient(135deg, #7ad957, #30b83f);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.purple {
|
|
||||||
background: linear-gradient(135deg, #a78bfa, #7c3aed);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.orange {
|
|
||||||
background: linear-gradient(135deg, #fbbf24, #f59e0b);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.cyan {
|
|
||||||
background: linear-gradient(135deg, #2dd4bf, #14b8a6);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.metric-content {
|
|
||||||
min-width: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.metric-label {
|
|
||||||
margin-bottom: 8px;
|
|
||||||
font-size: 14px;
|
|
||||||
color: var(--el-text-color-regular);
|
|
||||||
}
|
|
||||||
|
|
||||||
.metric-value {
|
|
||||||
overflow: hidden;
|
|
||||||
font-size: 26px;
|
|
||||||
font-weight: 700;
|
|
||||||
line-height: 1.25;
|
|
||||||
color: var(--el-text-color-primary);
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.metric-unit {
|
|
||||||
margin-left: 4px;
|
|
||||||
font-size: 13px;
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
|
|
||||||
.metric-sub {
|
|
||||||
display: flex;
|
|
||||||
min-height: 22px;
|
|
||||||
margin-top: 8px;
|
|
||||||
font-size: 13px;
|
|
||||||
color: var(--el-text-color-regular);
|
|
||||||
align-items: center;
|
|
||||||
gap: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.metric-change {
|
|
||||||
display: inline-flex;
|
|
||||||
color: var(--el-color-danger);
|
|
||||||
align-items: center;
|
|
||||||
gap: 2px;
|
|
||||||
|
|
||||||
&.down {
|
|
||||||
color: var(--el-color-success);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.chart-row,
|
|
||||||
.detail-row {
|
|
||||||
margin-bottom: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.overview-panel {
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.empty-panel {
|
|
||||||
display: flex;
|
|
||||||
min-height: 520px;
|
|
||||||
margin-bottom: 0;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.panel-header {
|
|
||||||
display: flex;
|
|
||||||
height: 32px;
|
|
||||||
margin-bottom: 8px;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
|
|
||||||
.panel-title {
|
|
||||||
display: inline-flex;
|
|
||||||
font-size: 16px;
|
|
||||||
font-weight: 700;
|
|
||||||
color: var(--el-text-color-primary);
|
|
||||||
align-items: center;
|
|
||||||
gap: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.panel-info {
|
|
||||||
font-size: 15px;
|
|
||||||
color: var(--el-color-primary-light-3);
|
|
||||||
}
|
|
||||||
|
|
||||||
.panel-actions {
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 4px;
|
|
||||||
|
|
||||||
.el-button {
|
|
||||||
width: 30px;
|
|
||||||
height: 30px;
|
|
||||||
padding: 0;
|
|
||||||
border: 1px solid var(--el-border-color-light);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.rank-index {
|
|
||||||
display: inline-flex;
|
|
||||||
width: 22px;
|
|
||||||
height: 22px;
|
|
||||||
font-size: 12px;
|
|
||||||
font-weight: 700;
|
|
||||||
color: #606266;
|
|
||||||
background: #eef1f6;
|
|
||||||
border-radius: 50%;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
|
|
||||||
&.rank-1 {
|
|
||||||
color: #fff;
|
|
||||||
background: #f5a400;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.rank-2 {
|
|
||||||
color: #fff;
|
|
||||||
background: #aab2bf;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.rank-3 {
|
|
||||||
color: #fff;
|
|
||||||
background: #d99458;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 1400px) {
|
|
||||||
.metric-grid {
|
|
||||||
grid-template-columns: repeat(3, minmax(180px, 1fr));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 900px) {
|
|
||||||
.metric-grid {
|
|
||||||
grid-template-columns: repeat(2, minmax(160px, 1fr));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 640px) {
|
|
||||||
.metric-grid {
|
|
||||||
grid-template-columns: 1fr;
|
|
||||||
}
|
|
||||||
|
|
||||||
.metric-card {
|
|
||||||
padding: 18px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
Loading…
Reference in New Issue