10 changed files with 1416 additions and 117 deletions
@ -0,0 +1,9 @@ |
|||||||
|
import request from "@/utils/request"; |
||||||
|
// 历史天气查询
|
||||||
|
export function weatherTempData(query) { |
||||||
|
return request({ |
||||||
|
url: "/device/cs/getWeatherTemp", |
||||||
|
method: "get", |
||||||
|
params: query, |
||||||
|
}); |
||||||
|
} |
@ -0,0 +1,368 @@ |
|||||||
|
<template> |
||||||
|
<div class="app-container"> |
||||||
|
<div class="btn-condition"> |
||||||
|
<div class="condition-left" v-show="showSearch"> |
||||||
|
<el-form |
||||||
|
:model="queryParams" |
||||||
|
ref="queryForm" |
||||||
|
size="small" |
||||||
|
:inline="true" |
||||||
|
label-width="68px" |
||||||
|
> |
||||||
|
<el-form-item label="日期" prop="msgCode"> |
||||||
|
<el-date-picker |
||||||
|
v-model="monthValue" |
||||||
|
type="month" |
||||||
|
placeholder="选择月" |
||||||
|
value-format="yyyy-MM" |
||||||
|
> |
||||||
|
</el-date-picker> |
||||||
|
</el-form-item> |
||||||
|
</el-form> |
||||||
|
<div class="primary-btn"> |
||||||
|
<el-button |
||||||
|
type="primary" |
||||||
|
icon="el-icon-search" |
||||||
|
size="mini" |
||||||
|
@click="handleQuery" |
||||||
|
>搜索</el-button |
||||||
|
> |
||||||
|
</div> |
||||||
|
<div class="cancel-btn"> |
||||||
|
<el-button |
||||||
|
type="cancel" |
||||||
|
icon="el-icon-refresh" |
||||||
|
size="mini" |
||||||
|
@click="resetQuery" |
||||||
|
>重置</el-button |
||||||
|
> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
<el-row :gutter="10" class="mb8"> |
||||||
|
<!-- <el-col :span="1.5"> |
||||||
|
<div class="warning-btn" v-hasPermi="['system:post:export']"> |
||||||
|
<el-button |
||||||
|
type="warning" |
||||||
|
icon="el-icon-download" |
||||||
|
size="mini" |
||||||
|
@click="handleExport" |
||||||
|
>导出</el-button |
||||||
|
> |
||||||
|
</div> |
||||||
|
</el-col> --> |
||||||
|
</el-row> |
||||||
|
<div class="charts" ref="chart_ref"></div> |
||||||
|
<el-table |
||||||
|
v-loading="loading" |
||||||
|
:data="postList" |
||||||
|
stripe |
||||||
|
:cell-style="tableRowStyle" |
||||||
|
> |
||||||
|
<el-table-column label="日期" align="center" prop="dateAndWeek" /> |
||||||
|
<el-table-column label="最高气温" align="center" prop="maxTemp" /> |
||||||
|
<el-table-column label="最低气温" align="center" prop="minTemp" /> |
||||||
|
<el-table-column label="天气" align="center" prop="weatherConditions" /> |
||||||
|
<el-table-column label="风向" align="center" prop="windDirection" /> |
||||||
|
</el-table> |
||||||
|
|
||||||
|
<pagination |
||||||
|
v-show="total > 0" |
||||||
|
:total="total" |
||||||
|
:page.sync="queryParams.pageNum" |
||||||
|
:limit.sync="queryParams.pageSize" |
||||||
|
@pagination="getList" |
||||||
|
/> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
import { weatherTempData } from "@/api/centerairC/temHistory"; |
||||||
|
import * as echarts from "echarts"; |
||||||
|
export default { |
||||||
|
name: "temHistoryQuery", |
||||||
|
data() { |
||||||
|
return { |
||||||
|
// 遮罩层 |
||||||
|
loading: true, |
||||||
|
// 选中数组 |
||||||
|
ids: [], |
||||||
|
// 非单个禁用 |
||||||
|
single: true, |
||||||
|
// 非多个禁用 |
||||||
|
multiple: true, |
||||||
|
// 显示搜索条件 |
||||||
|
showSearch: true, |
||||||
|
// 总条数 |
||||||
|
total: 0, |
||||||
|
// 表格数据 |
||||||
|
postList: [], |
||||||
|
// 弹出层标题 |
||||||
|
title: "", |
||||||
|
// 是否显示弹出层 |
||||||
|
open: false, |
||||||
|
// 查询参数 |
||||||
|
queryParams: { |
||||||
|
pageNum: 1, |
||||||
|
pageSize: 10, |
||||||
|
startTime: "", |
||||||
|
endTime: "", |
||||||
|
}, |
||||||
|
monthValue: "", |
||||||
|
chartInstance: null, |
||||||
|
option: {}, |
||||||
|
}; |
||||||
|
}, |
||||||
|
created() { |
||||||
|
// 获取当前日期 |
||||||
|
const currentDate = new Date(); |
||||||
|
// 获取当前年份 |
||||||
|
const year = currentDate.getFullYear(); |
||||||
|
// 获取当前月份,注意月份是从 0 开始的,所以要加 1 |
||||||
|
const month = String(currentDate.getMonth() + 1).padStart(2, "0"); |
||||||
|
// 格式化日期为 yyyy-MM 格式 |
||||||
|
this.monthValue = `${year}-${month}`; |
||||||
|
}, |
||||||
|
mounted() { |
||||||
|
this.initChart(); |
||||||
|
window.addEventListener("resize", this.screenAdapter); |
||||||
|
this.screenAdapter(); |
||||||
|
this.getChartData(); |
||||||
|
this.getList(); |
||||||
|
}, |
||||||
|
methods: { |
||||||
|
tableRowStyle({ row, column, rowIndex, columnIndex }) { |
||||||
|
// 修改颜色 |
||||||
|
if (columnIndex === 1) { |
||||||
|
return "color: #fd1e00;!important;text-align:center"; |
||||||
|
} |
||||||
|
if (columnIndex === 2) { |
||||||
|
return "color: #3390ff;!important;text-align:center"; |
||||||
|
} |
||||||
|
if (columnIndex === 4) { |
||||||
|
return "color: #75d148;!important;text-align:center"; |
||||||
|
} |
||||||
|
// return "text-align:center"; |
||||||
|
}, |
||||||
|
/** 查询报警编码列表 */ |
||||||
|
getList() { |
||||||
|
this.loading = true; |
||||||
|
this.queryParams.startTime = this.queryParams.endTime = this.monthValue; |
||||||
|
console.log("参数", this.queryParams); |
||||||
|
weatherTempData(this.queryParams).then((response) => { |
||||||
|
this.postList = response.rows; |
||||||
|
this.total = response.total; |
||||||
|
this.loading = false; |
||||||
|
}); |
||||||
|
}, |
||||||
|
getChartData() { |
||||||
|
this.loading = true; |
||||||
|
this.queryParams.pageNum = 0; |
||||||
|
this.queryParams.startTime = this.queryParams.endTime = this.monthValue; |
||||||
|
console.log("图表参数", this.queryParams); |
||||||
|
weatherTempData(this.queryParams).then((response) => { |
||||||
|
console.log("处理值然后渲染"); |
||||||
|
if (response.rows.length > 0) { |
||||||
|
let data = response.rows; |
||||||
|
let timeValue = []; |
||||||
|
let hightValue = []; |
||||||
|
let lowValue = []; |
||||||
|
data.forEach((element) => { |
||||||
|
timeValue.push(element.weatherDate); |
||||||
|
hightValue.push(element.maxTemp); |
||||||
|
lowValue.push(element.minTemp); |
||||||
|
}); |
||||||
|
let adapterOption = {}; |
||||||
|
adapterOption = { |
||||||
|
xAxis: { |
||||||
|
data: timeValue, |
||||||
|
}, |
||||||
|
series: [ |
||||||
|
{ |
||||||
|
data: hightValue, |
||||||
|
//折线颜色 |
||||||
|
itemStyle: { |
||||||
|
color: "rgb(18, 126, 226)", //折线的颜色 |
||||||
|
}, |
||||||
|
lineStyle: { |
||||||
|
color: "rgb(18, 126, 226)", //折线点的颜色 |
||||||
|
}, |
||||||
|
}, |
||||||
|
{ |
||||||
|
data: lowValue, |
||||||
|
//折线颜色 |
||||||
|
itemStyle: { |
||||||
|
color: "rgb(250, 169, 19)", //折线的颜色 |
||||||
|
}, |
||||||
|
lineStyle: { |
||||||
|
color: "rgb(250, 169, 19)", //折线点的颜色 |
||||||
|
}, |
||||||
|
}, |
||||||
|
], |
||||||
|
}; |
||||||
|
//记得重新给配置项给实例对象。只要实例对象.chartInstance不变,option就可以多次配置不同的条件。也可以配置一个dataoption只写需要从后台请求的数据相关 |
||||||
|
this.chartInstance.setOption(adapterOption); |
||||||
|
//手动的调用图标对象的resize才能产生效果 |
||||||
|
this.chartInstance.resize(); |
||||||
|
} else { |
||||||
|
let adapterOption = {}; |
||||||
|
adapterOption = { |
||||||
|
xAxis: { |
||||||
|
data: [], |
||||||
|
}, |
||||||
|
series: [ |
||||||
|
{ |
||||||
|
data: [], |
||||||
|
}, |
||||||
|
{ |
||||||
|
data: [], |
||||||
|
}, |
||||||
|
], |
||||||
|
}; |
||||||
|
//记得重新给配置项给实例对象。只要实例对象.chartInstance不变,option就可以多次配置不同的条件。也可以配置一个dataoption只写需要从后台请求的数据相关 |
||||||
|
this.chartInstance.setOption(adapterOption); |
||||||
|
//手动的调用图标对象的resize才能产生效果 |
||||||
|
this.chartInstance.resize(); |
||||||
|
} |
||||||
|
}); |
||||||
|
}, |
||||||
|
/** 搜索按钮操作 */ |
||||||
|
handleQuery() { |
||||||
|
this.queryParams.pageNum = 1; |
||||||
|
this.getList(); |
||||||
|
this.getChartData(); |
||||||
|
}, |
||||||
|
/** 重置按钮操作 */ |
||||||
|
resetQuery() { |
||||||
|
this.handleQuery(); |
||||||
|
}, |
||||||
|
/** 导出按钮操作 */ |
||||||
|
handleExport() { |
||||||
|
this.download( |
||||||
|
"device/gateway/export", |
||||||
|
{ |
||||||
|
...this.queryParams, |
||||||
|
}, |
||||||
|
`post_${new Date().getTime()}.xlsx` |
||||||
|
); |
||||||
|
}, |
||||||
|
// 折线图自适应+ 根据按钮切换图例仅限一条且不可点击+ 折线图数据 |
||||||
|
screenAdapter() { |
||||||
|
//自己定义的比较合适的适配大小,2.6 mes_ref是图表盒子 |
||||||
|
const titleFontSize = this.$refs.chart_ref.offsetWidth / 130; |
||||||
|
//因为option可以多次配置的,所以这里的option只需要写 需要配置大小的相关数据 |
||||||
|
const adapterOption = {}; |
||||||
|
//记得重新给配置项给实例对象。只要实例对象.chartInstance不变,option就可以多次配置不同的条件。也可以配置一个dataoption只写需要从后台请求的数据相关 |
||||||
|
this.chartInstance.setOption(adapterOption); |
||||||
|
//手动的调用图标对象的resize才能产生效果 |
||||||
|
this.chartInstance.resize(); |
||||||
|
}, |
||||||
|
//初始化chartInstance对象 |
||||||
|
initChart() { |
||||||
|
this.chartInstance = echarts.init(this.$refs.chart_ref); |
||||||
|
this.option = { |
||||||
|
tooltip: { |
||||||
|
// 设置触发方式为 axis,鼠标移动到 x 轴对应位置时触发 |
||||||
|
trigger: "axis", |
||||||
|
}, |
||||||
|
legend: { |
||||||
|
show: false, |
||||||
|
}, |
||||||
|
grid: { |
||||||
|
top: "10%", |
||||||
|
left: "4%", |
||||||
|
right: "6%", |
||||||
|
bottom: "3%", |
||||||
|
containLabel: true, |
||||||
|
}, |
||||||
|
xAxis: { |
||||||
|
type: "category", |
||||||
|
//设置为true代表离零刻度间隔一段距离 |
||||||
|
boundaryGap: true, |
||||||
|
// 修饰刻度标签的颜色即x坐标数据 |
||||||
|
axisLabel: { |
||||||
|
// interval: 0, //强制显示所有x轴数据 |
||||||
|
// rotate: 30, //x轴坐标字体倾斜30度 |
||||||
|
color: "rgba(255, 255, 255, 1)", |
||||||
|
}, |
||||||
|
axisTick: { |
||||||
|
show: false, // 不显示坐标轴刻度线 |
||||||
|
}, |
||||||
|
// x坐标轴的颜色 |
||||||
|
axisLine: { |
||||||
|
show: true, |
||||||
|
lineStyle: { |
||||||
|
color: "#365576", |
||||||
|
}, |
||||||
|
}, |
||||||
|
splitLine: { |
||||||
|
lineStyle: { |
||||||
|
color: "#e2e6f0", |
||||||
|
}, |
||||||
|
}, //x轴分割线 |
||||||
|
}, |
||||||
|
yAxis: { |
||||||
|
min: 0, |
||||||
|
// max:20, |
||||||
|
// // // min:'dataMin', |
||||||
|
// // // max:'dataMax', |
||||||
|
// name: "kwh", // 第一个 y 轴的单位描述 |
||||||
|
// 设置 name 的样式 |
||||||
|
nameTextStyle: { |
||||||
|
color: "rgba(255, 255, 255, 1)", |
||||||
|
fontSize: 12, |
||||||
|
}, |
||||||
|
miniInterval: 5, |
||||||
|
type: "value", |
||||||
|
// 修饰刻度标签的颜色即y坐标数据 |
||||||
|
axisLabel: { |
||||||
|
color: "rgba(255, 255, 255, 1)", |
||||||
|
}, |
||||||
|
// 显示y坐标轴 |
||||||
|
axisLine: { |
||||||
|
show: true, |
||||||
|
lineStyle: { |
||||||
|
color: "#365576", // 设置 y 轴线的颜色 |
||||||
|
}, |
||||||
|
}, |
||||||
|
//y轴分割线段数 |
||||||
|
// splitNumber: 10, |
||||||
|
// 修改y轴分割线的颜色 |
||||||
|
splitLine: { |
||||||
|
lineStyle: { |
||||||
|
color: "#1a3d62", // 设置分割线的颜色 |
||||||
|
type: "dashed", // 设置分割线为虚线 |
||||||
|
}, |
||||||
|
}, |
||||||
|
}, |
||||||
|
series: [ |
||||||
|
{ |
||||||
|
type: "line", |
||||||
|
// 拐点大小 |
||||||
|
symbolSize: 8, |
||||||
|
symbol: "circle", |
||||||
|
name: "最高气温", |
||||||
|
}, |
||||||
|
{ |
||||||
|
type: "line", |
||||||
|
// 拐点大小 |
||||||
|
symbolSize: 8, |
||||||
|
symbol: "circle", |
||||||
|
name: "最低气温", |
||||||
|
}, |
||||||
|
], |
||||||
|
}; |
||||||
|
//把配置项给实例对象 |
||||||
|
this.chartInstance.setOption(this.option, true); |
||||||
|
}, |
||||||
|
}, |
||||||
|
}; |
||||||
|
</script> |
||||||
|
<style lang="scss" scoped> |
||||||
|
.charts { |
||||||
|
width: 100%; |
||||||
|
height: 300px; |
||||||
|
margin-bottom: 0.1rem; |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,332 @@ |
|||||||
|
<template> |
||||||
|
<div class="sys_content"> |
||||||
|
<div class="charts" ref="chart_ref"></div> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
import * as echarts from "echarts"; |
||||||
|
export default { |
||||||
|
props: { |
||||||
|
subData: { |
||||||
|
type: Array, |
||||||
|
required: true, |
||||||
|
}, |
||||||
|
}, |
||||||
|
data() { |
||||||
|
return { |
||||||
|
chartInstance: null, |
||||||
|
option: {}, |
||||||
|
chartData1: "", |
||||||
|
chartData2: "", |
||||||
|
allData: "", |
||||||
|
}; |
||||||
|
}, |
||||||
|
watch: { |
||||||
|
subData: { |
||||||
|
immediate: true, // 页面加载时立即触发一次监听 |
||||||
|
handler(newVal) { |
||||||
|
console.log("检测到传功来的数据", this.subData); |
||||||
|
if (Object.keys(newVal).length > 0) { |
||||||
|
console.log("newval", newVal); |
||||||
|
let data = newVal; |
||||||
|
this.chartData1 = ""; |
||||||
|
this.chartData2 = ""; |
||||||
|
data.forEach((item) => { |
||||||
|
if (item.name.includes("运行")) { |
||||||
|
this.chartData1 = parseInt(item.value); |
||||||
|
} |
||||||
|
if (item.name.includes("停止")) { |
||||||
|
this.chartData2 = parseInt(item.value); |
||||||
|
} |
||||||
|
// 计算总和 |
||||||
|
this.allData = this.chartData1 + this.chartData2; |
||||||
|
}); |
||||||
|
this.$nextTick(() => { |
||||||
|
// 销毁现有的 ECharts 实例 |
||||||
|
if (this.chartInstance) { |
||||||
|
this.chartInstance.dispose(); |
||||||
|
} |
||||||
|
// 重新初始化图表 |
||||||
|
this.initChart(); |
||||||
|
}); |
||||||
|
} |
||||||
|
}, |
||||||
|
}, |
||||||
|
}, |
||||||
|
mounted() { |
||||||
|
this.initChart(); |
||||||
|
window.addEventListener("resize", this.screenAdapter); |
||||||
|
this.screenAdapter(); |
||||||
|
}, |
||||||
|
destroyed() { |
||||||
|
//取消监听器 |
||||||
|
window.removeEventListener("resize", this.screenAdapter); |
||||||
|
}, |
||||||
|
methods: { |
||||||
|
// 折线图自适应+ 根据按钮切换图例仅限一条且不可点击+ 折线图数据 |
||||||
|
screenAdapter() { |
||||||
|
//自己定义的比较合适的适配大小,2.6 mes_ref是图表盒子 |
||||||
|
const titleFontSize = this.$refs.chart_ref.offsetWidth / 100; |
||||||
|
//因为option可以多次配置的,所以这里的option只需要写 需要配置大小的相关数据 |
||||||
|
const adapterOption = {}; |
||||||
|
//记得重新给配置项给实例对象。只要实例对象.chartInstance不变,option就可以多次配置不同的条件。也可以配置一个dataoption只写需要从后台请求的数据相关 |
||||||
|
this.chartInstance.setOption(adapterOption); |
||||||
|
//手动的调用图标对象的resize才能产生效果 |
||||||
|
this.chartInstance.resize(); |
||||||
|
}, |
||||||
|
//初始化chartInstance对象 |
||||||
|
initChart() { |
||||||
|
var dataStyle = { |
||||||
|
normal: { |
||||||
|
label: { |
||||||
|
show: false, |
||||||
|
}, |
||||||
|
labelLine: { |
||||||
|
show: false, |
||||||
|
}, |
||||||
|
shadowBlur: 40, |
||||||
|
borderWidth: 10, |
||||||
|
shadowColor: "rgba(0, 0, 0, 0)", //边框阴影 |
||||||
|
}, |
||||||
|
}; |
||||||
|
var placeHolderStyle = { |
||||||
|
normal: { |
||||||
|
color: "#013e79", |
||||||
|
label: { |
||||||
|
show: false, |
||||||
|
}, |
||||||
|
labelLine: { |
||||||
|
show: false, |
||||||
|
}, |
||||||
|
}, |
||||||
|
emphasis: { |
||||||
|
color: "#013e79", |
||||||
|
}, |
||||||
|
}; |
||||||
|
let that = this; |
||||||
|
const titleFontSize = (this.$refs.chart_ref.offsetWidth / 100) * 2; |
||||||
|
this.chartInstance = echarts.init(this.$refs.chart_ref); |
||||||
|
this.option = { |
||||||
|
title: { |
||||||
|
subtext: "运行状态", |
||||||
|
textStyle: { |
||||||
|
color: "#ffffff", |
||||||
|
}, |
||||||
|
subtextStyle: { |
||||||
|
color: "#ffffff", |
||||||
|
}, |
||||||
|
textAlign: "center", |
||||||
|
x: "31%", |
||||||
|
y: "43%", //距离上边的距离 |
||||||
|
}, |
||||||
|
tooltip: { |
||||||
|
trigger: "item", |
||||||
|
formatter: "{a} <br/>{b} : {c} ({d}%)", |
||||||
|
}, |
||||||
|
legend: { |
||||||
|
// 设置图例显示在右侧 |
||||||
|
right: 0, |
||||||
|
// 设置图例垂直居中 |
||||||
|
top: "middle", |
||||||
|
itemWidth: titleFontSize, |
||||||
|
itemHeight: titleFontSize, |
||||||
|
itemGap: titleFontSize * 2, |
||||||
|
formatter: function (name) { |
||||||
|
var arr = []; |
||||||
|
// 动态查找包含当前name的series索引 |
||||||
|
let seriesIndex = -1; |
||||||
|
for (let i = 0; i < that.option.series.length; i++) { |
||||||
|
const seriesData = that.option.series[i].data; |
||||||
|
if (seriesData.some((item) => item.name === name)) { |
||||||
|
seriesIndex = i; |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if (seriesIndex === -1) return name; // 未找到匹配系列 |
||||||
|
|
||||||
|
const data = that.option.series[seriesIndex].data; // 使用动态索引 |
||||||
|
let total = that.allData; |
||||||
|
let currentValue = 0; |
||||||
|
|
||||||
|
// 计算总和和当前值 |
||||||
|
data.forEach((item) => { |
||||||
|
if (item.name) { |
||||||
|
// 排除空名的占位数据 |
||||||
|
total += item.value; |
||||||
|
if (item.name === name) { |
||||||
|
currentValue = item.value; |
||||||
|
} |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
const percentage = |
||||||
|
currentValue === 0 |
||||||
|
? "0.00" |
||||||
|
: ((currentValue / total) * 100).toFixed(2); |
||||||
|
|
||||||
|
arr.push( |
||||||
|
"{name|" + name + "}", |
||||||
|
"{text|: \n}", |
||||||
|
"{value|" + currentValue + " }", |
||||||
|
"{percentage| " + percentage + "%}" |
||||||
|
); |
||||||
|
return arr.join(""); |
||||||
|
}, |
||||||
|
textStyle: { |
||||||
|
color: function (name) { |
||||||
|
// 动态匹配系列颜色 |
||||||
|
for (let i = 0; i < that.option.series.length; i++) { |
||||||
|
const item = that.option.series[i].data.find( |
||||||
|
(d) => d.name === name |
||||||
|
); |
||||||
|
if (item) { |
||||||
|
// 返回实际颜色(处理渐变色) |
||||||
|
return ( |
||||||
|
item.itemStyle?.normal?.color?.colorStops?.[0]?.color || |
||||||
|
item.itemStyle?.color || |
||||||
|
"#ffffff" |
||||||
|
); |
||||||
|
} |
||||||
|
} |
||||||
|
return "#ffffff"; // 默认颜色 |
||||||
|
}, |
||||||
|
rich: { |
||||||
|
name: { |
||||||
|
align: "left", |
||||||
|
fontSize: titleFontSize * 2.3, |
||||||
|
// 增加行高来扩大间隔 |
||||||
|
lineHeight: titleFontSize * 3.3, |
||||||
|
}, |
||||||
|
text: { |
||||||
|
align: "left", |
||||||
|
fontSize: titleFontSize * 2.3, |
||||||
|
}, |
||||||
|
value: { |
||||||
|
align: "left", |
||||||
|
fontSize: titleFontSize * 2.3, |
||||||
|
// color: function (params) { |
||||||
|
// let data = adapterOption.series[1].data; |
||||||
|
// return data.itemStyle.color({ dataIndex: params.dataIndex }); |
||||||
|
// }, |
||||||
|
}, |
||||||
|
percentage: { |
||||||
|
align: "left", |
||||||
|
fontSize: titleFontSize * 2.3, |
||||||
|
// color: function (params) { |
||||||
|
// let data = adapterOption.series[1].data; |
||||||
|
// return data.itemStyle.color({ dataIndex: params.dataIndex }); |
||||||
|
// }, |
||||||
|
}, |
||||||
|
}, |
||||||
|
}, |
||||||
|
}, |
||||||
|
series: [ |
||||||
|
{ |
||||||
|
name: "风柜系统", |
||||||
|
type: "pie", |
||||||
|
clockWise: false, |
||||||
|
radius: [66, 80], |
||||||
|
center: ["32%", "50%"], |
||||||
|
itemStyle: dataStyle, |
||||||
|
hoverAnimation: false, |
||||||
|
startAngle: 90, |
||||||
|
label: { |
||||||
|
borderRadius: "10", |
||||||
|
}, |
||||||
|
data: [ |
||||||
|
{ |
||||||
|
value: this.chartData1, |
||||||
|
name: "运行数", |
||||||
|
itemStyle: { |
||||||
|
normal: { |
||||||
|
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ |
||||||
|
{ |
||||||
|
offset: 0, |
||||||
|
color: "#277dff", |
||||||
|
}, |
||||||
|
{ |
||||||
|
offset: 1, |
||||||
|
color: "#277dff", |
||||||
|
}, |
||||||
|
]), |
||||||
|
}, |
||||||
|
}, |
||||||
|
}, |
||||||
|
{ |
||||||
|
value: this.allData, |
||||||
|
name: "", |
||||||
|
tooltip: { |
||||||
|
show: false, |
||||||
|
}, |
||||||
|
itemStyle: placeHolderStyle, |
||||||
|
}, |
||||||
|
], |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: "风柜系统", |
||||||
|
type: "pie", |
||||||
|
clockWise: false, |
||||||
|
radius: [36, 50], |
||||||
|
center: ["32%", "50%"], |
||||||
|
itemStyle: dataStyle, |
||||||
|
hoverAnimation: false, |
||||||
|
startAngle: 90, |
||||||
|
data: [ |
||||||
|
{ |
||||||
|
value: this.chartData2, |
||||||
|
name: "停止数", |
||||||
|
itemStyle: { |
||||||
|
normal: { |
||||||
|
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ |
||||||
|
{ |
||||||
|
offset: 0, |
||||||
|
color: "#9ab7dc", |
||||||
|
}, |
||||||
|
{ |
||||||
|
offset: 1, |
||||||
|
color: "#9ab7dc", |
||||||
|
}, |
||||||
|
]), |
||||||
|
}, |
||||||
|
}, |
||||||
|
}, |
||||||
|
{ |
||||||
|
value: this.allData, |
||||||
|
name: "", |
||||||
|
tooltip: { |
||||||
|
show: false, |
||||||
|
}, |
||||||
|
itemStyle: placeHolderStyle, |
||||||
|
}, |
||||||
|
], |
||||||
|
}, |
||||||
|
], |
||||||
|
}; |
||||||
|
//把配置项给实例对象 |
||||||
|
this.chartInstance.setOption(this.option, true); |
||||||
|
}, |
||||||
|
}, |
||||||
|
}; |
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang="scss" scoped> |
||||||
|
.sys_content { |
||||||
|
padding: 20px; |
||||||
|
.charts { |
||||||
|
width: 100%; |
||||||
|
height: 250px; |
||||||
|
} |
||||||
|
} |
||||||
|
// 媒体查询,适配大于2000px分辨率的大屏样式 |
||||||
|
@media (min-width: 2000px) { |
||||||
|
.sys_content { |
||||||
|
padding: 0.2rem !important; |
||||||
|
.charts { |
||||||
|
width: 100%; |
||||||
|
height: 2.5rem !important; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,142 @@ |
|||||||
|
<template> |
||||||
|
<div class="card-div"> |
||||||
|
<div class="card-li room-temp"> |
||||||
|
<div class="card-header"> |
||||||
|
<h2 class="card-title">回水平均温度</h2> |
||||||
|
<div class="icon"> |
||||||
|
<i class="fas fa-home"></i> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<div class="thermometer"> |
||||||
|
<div class="temprogress" :style="{ height: temData1 * 2 + '%' }"></div> |
||||||
|
</div> |
||||||
|
<div class="temperature">{{temData1}}℃</div> |
||||||
|
</div> |
||||||
|
<div class="card-li amb-temp"> |
||||||
|
<div class="card-header"> |
||||||
|
<h2 class="card-title">供水平均温度</h2> |
||||||
|
<div class="icon"> |
||||||
|
<i class="fas fa-home"></i> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<div class="thermometer"> |
||||||
|
<div class="temprogress" :style="{ height: temData2 * 2 + '%' }"></div> |
||||||
|
</div> |
||||||
|
<div class="temperature">{{temData2}}℃</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
export default { |
||||||
|
props: { |
||||||
|
subData: { |
||||||
|
type: Array, |
||||||
|
required: true, |
||||||
|
}, |
||||||
|
}, |
||||||
|
data() { |
||||||
|
return { |
||||||
|
temData1: "", |
||||||
|
temData2: "", |
||||||
|
}; |
||||||
|
}, |
||||||
|
watch: { |
||||||
|
subData: { |
||||||
|
immediate: true, // 页面加载时立即触发一次监听 |
||||||
|
handler(newVal) { |
||||||
|
console.log("检测到传功来的数据", this.subData); |
||||||
|
if (Object.keys(newVal).length > 0) { |
||||||
|
console.log("newval", newVal); |
||||||
|
let data = newVal; |
||||||
|
this.temData1 = ""; |
||||||
|
this.temData2 = ""; |
||||||
|
data.forEach((item) => { |
||||||
|
if (item.name.includes("回水")) { |
||||||
|
this.temData1 = parseInt(item.value); |
||||||
|
} |
||||||
|
if (item.name.includes("供水")) { |
||||||
|
this.temData2 = parseInt(item.value); |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
}, |
||||||
|
}, |
||||||
|
}, |
||||||
|
}; |
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang="scss" scoped> |
||||||
|
.card-div { |
||||||
|
width: 100%; |
||||||
|
display: flex; |
||||||
|
flex-direction: row; |
||||||
|
justify-content: space-between; |
||||||
|
align-items: center; |
||||||
|
.card-li { |
||||||
|
width: 50%; |
||||||
|
padding: 0.2rem 0; |
||||||
|
display: flex; |
||||||
|
flex-direction: column; |
||||||
|
align-items: center; |
||||||
|
.card-header { |
||||||
|
display: flex; |
||||||
|
justify-content: space-between; |
||||||
|
align-items: center; |
||||||
|
margin-bottom: 0.1rem; |
||||||
|
.card-title { |
||||||
|
font-size: 15px; |
||||||
|
font-weight: 600; |
||||||
|
color: #ffffff; |
||||||
|
} |
||||||
|
} |
||||||
|
.temperature { |
||||||
|
font-size: 20px; |
||||||
|
font-weight: 700; |
||||||
|
position: relative; |
||||||
|
display: inline-block; |
||||||
|
} |
||||||
|
.thermometer { |
||||||
|
height: 180px; |
||||||
|
width: 40px; |
||||||
|
background: #3d5581; |
||||||
|
border-radius: 20px; |
||||||
|
margin: 0 auto 0.25rem; |
||||||
|
overflow: hidden; |
||||||
|
box-shadow: inset 0 0 1rem rgba(0, 0, 0, 0.1); |
||||||
|
position: relative; |
||||||
|
} |
||||||
|
.temprogress { |
||||||
|
position: absolute; |
||||||
|
bottom: 0; |
||||||
|
width: 100%; |
||||||
|
border-top-left-radius: 20px; |
||||||
|
border-top-right-radius:20px; |
||||||
|
background: linear-gradient(to top, #3498db, #2ecc71) !important; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
@media (min-width: 2000px) { |
||||||
|
.card-div { |
||||||
|
.card-li { |
||||||
|
.card-header { |
||||||
|
.card-title { |
||||||
|
font-size: 0.15rem !important; |
||||||
|
} |
||||||
|
} |
||||||
|
.temperature { |
||||||
|
font-size: 0.2rem !important; |
||||||
|
} |
||||||
|
.thermometer { |
||||||
|
height: 1.8rem !important; |
||||||
|
width: 0.4rem !important; |
||||||
|
border-radius: 0.2rem !important; |
||||||
|
} |
||||||
|
.temprogress { |
||||||
|
border-top-left-radius: 0.2rem !important; |
||||||
|
border-top-right-radius:0.2rem !important; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,331 @@ |
|||||||
|
<template> |
||||||
|
<div class="sys_content"> |
||||||
|
<div class="charts" ref="chart_ref"></div> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
import * as echarts from "echarts"; |
||||||
|
export default { |
||||||
|
props: { |
||||||
|
subData: { |
||||||
|
type: Array, |
||||||
|
required: true, |
||||||
|
}, |
||||||
|
}, |
||||||
|
data() { |
||||||
|
return { |
||||||
|
chartInstance: null, |
||||||
|
option: {}, |
||||||
|
chartData1: "", |
||||||
|
chartData2: "", |
||||||
|
allData: "", |
||||||
|
}; |
||||||
|
}, |
||||||
|
watch: { |
||||||
|
subData: { |
||||||
|
immediate: true, // 页面加载时立即触发一次监听 |
||||||
|
handler(newVal) { |
||||||
|
console.log("检测到传功来的数据", this.subData); |
||||||
|
if (Object.keys(newVal).length > 0) { |
||||||
|
console.log("newval", newVal); |
||||||
|
let data = newVal; |
||||||
|
this.chartData1 = ""; |
||||||
|
this.chartData2 = ""; |
||||||
|
data.forEach((item) => { |
||||||
|
if (item.name.includes("在线")) { |
||||||
|
this.chartData1 = parseInt(item.value); |
||||||
|
} |
||||||
|
if (item.name.includes("离线")) { |
||||||
|
this.chartData2 = parseInt(item.value); |
||||||
|
} |
||||||
|
// 计算总和 |
||||||
|
this.allData = this.chartData1 + this.chartData2; |
||||||
|
}); |
||||||
|
this.$nextTick(() => { |
||||||
|
// 销毁现有的 ECharts 实例 |
||||||
|
if (this.chartInstance) { |
||||||
|
this.chartInstance.dispose(); |
||||||
|
} |
||||||
|
// 重新初始化图表 |
||||||
|
this.initChart(); |
||||||
|
}); |
||||||
|
} |
||||||
|
}, |
||||||
|
}, |
||||||
|
}, |
||||||
|
mounted() { |
||||||
|
this.initChart(); |
||||||
|
window.addEventListener("resize", this.screenAdapter); |
||||||
|
this.screenAdapter(); |
||||||
|
}, |
||||||
|
destroyed() { |
||||||
|
//取消监听器 |
||||||
|
window.removeEventListener("resize", this.screenAdapter); |
||||||
|
}, |
||||||
|
methods: { |
||||||
|
// 折线图自适应+ 根据按钮切换图例仅限一条且不可点击+ 折线图数据 |
||||||
|
screenAdapter() { |
||||||
|
//自己定义的比较合适的适配大小,2.6 mes_ref是图表盒子 |
||||||
|
const titleFontSize = this.$refs.chart_ref.offsetWidth / 100; |
||||||
|
//因为option可以多次配置的,所以这里的option只需要写 需要配置大小的相关数据 |
||||||
|
const adapterOption = {}; |
||||||
|
//记得重新给配置项给实例对象。只要实例对象.chartInstance不变,option就可以多次配置不同的条件。也可以配置一个dataoption只写需要从后台请求的数据相关 |
||||||
|
this.chartInstance.setOption(adapterOption); |
||||||
|
//手动的调用图标对象的resize才能产生效果 |
||||||
|
this.chartInstance.resize(); |
||||||
|
}, |
||||||
|
//初始化chartInstance对象 |
||||||
|
initChart() { |
||||||
|
var dataStyle = { |
||||||
|
normal: { |
||||||
|
label: { |
||||||
|
show: false, |
||||||
|
}, |
||||||
|
labelLine: { |
||||||
|
show: false, |
||||||
|
}, |
||||||
|
shadowBlur: 40, |
||||||
|
borderWidth: 10, |
||||||
|
shadowColor: "rgba(0, 0, 0, 0)", //边框阴影 |
||||||
|
}, |
||||||
|
}; |
||||||
|
var placeHolderStyle = { |
||||||
|
normal: { |
||||||
|
color: "#393d50", |
||||||
|
label: { |
||||||
|
show: false, |
||||||
|
}, |
||||||
|
labelLine: { |
||||||
|
show: false, |
||||||
|
}, |
||||||
|
}, |
||||||
|
emphasis: { |
||||||
|
color: "#393d50", |
||||||
|
}, |
||||||
|
}; |
||||||
|
let that = this; |
||||||
|
const titleFontSize = (this.$refs.chart_ref.offsetWidth / 100) * 2; |
||||||
|
this.chartInstance = echarts.init(this.$refs.chart_ref); |
||||||
|
this.option = { |
||||||
|
title: { |
||||||
|
subtext: "在线状态", |
||||||
|
textStyle: { |
||||||
|
color: "#ffffff", |
||||||
|
}, |
||||||
|
subtextStyle: { |
||||||
|
color: "#ffffff", |
||||||
|
}, |
||||||
|
textAlign: "center", |
||||||
|
x: "31%", |
||||||
|
y: "43%", //距离上边的距离 |
||||||
|
}, |
||||||
|
tooltip: { |
||||||
|
trigger: "item", |
||||||
|
formatter: "{a} <br/>{b} : {c} ({d}%)", |
||||||
|
}, |
||||||
|
legend: { |
||||||
|
// 设置图例显示在右侧 |
||||||
|
right: 0, |
||||||
|
// 设置图例垂直居中 |
||||||
|
top: "middle", |
||||||
|
itemWidth: titleFontSize, |
||||||
|
itemHeight: titleFontSize, |
||||||
|
itemGap: titleFontSize * 2, |
||||||
|
formatter: function (name) { |
||||||
|
var arr = []; |
||||||
|
// 动态查找包含当前name的series索引 |
||||||
|
let seriesIndex = -1; |
||||||
|
for (let i = 0; i < that.option.series.length; i++) { |
||||||
|
const seriesData = that.option.series[i].data; |
||||||
|
if (seriesData.some((item) => item.name === name)) { |
||||||
|
seriesIndex = i; |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if (seriesIndex === -1) return name; // 未找到匹配系列 |
||||||
|
|
||||||
|
const data = that.option.series[seriesIndex].data; // 使用动态索引 |
||||||
|
let total = that.allData; |
||||||
|
let currentValue = 0; |
||||||
|
|
||||||
|
// 计算总和和当前值 |
||||||
|
data.forEach((item) => { |
||||||
|
if (item.name) { |
||||||
|
// 排除空名的占位数据 |
||||||
|
if (item.name === name) { |
||||||
|
currentValue = item.value; |
||||||
|
} |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
const percentage = |
||||||
|
currentValue === 0 |
||||||
|
? "0.00" |
||||||
|
: ((currentValue / total) * 100).toFixed(2); |
||||||
|
|
||||||
|
arr.push( |
||||||
|
"{name|" + name + "}", |
||||||
|
"{text|: \n}", |
||||||
|
"{value|" + currentValue + " }", |
||||||
|
"{percentage| " + percentage + "%}" |
||||||
|
); |
||||||
|
return arr.join(""); |
||||||
|
}, |
||||||
|
textStyle: { |
||||||
|
color: function (name) { |
||||||
|
// 动态匹配系列颜色 |
||||||
|
for (let i = 0; i < that.option.series.length; i++) { |
||||||
|
const item = that.option.series[i].data.find( |
||||||
|
(d) => d.name === name |
||||||
|
); |
||||||
|
if (item) { |
||||||
|
// 返回实际颜色(处理渐变色) |
||||||
|
return ( |
||||||
|
item.itemStyle?.normal?.color?.colorStops?.[0]?.color || |
||||||
|
item.itemStyle?.color || |
||||||
|
"#ffffff" |
||||||
|
); |
||||||
|
} |
||||||
|
} |
||||||
|
return "#ffffff"; // 默认颜色 |
||||||
|
}, |
||||||
|
rich: { |
||||||
|
name: { |
||||||
|
align: "left", |
||||||
|
fontSize: titleFontSize * 2.3, |
||||||
|
// 增加行高来扩大间隔 |
||||||
|
lineHeight: titleFontSize * 3.3, |
||||||
|
}, |
||||||
|
text: { |
||||||
|
align: "left", |
||||||
|
fontSize: titleFontSize * 2.3, |
||||||
|
}, |
||||||
|
value: { |
||||||
|
align: "left", |
||||||
|
fontSize: titleFontSize * 2.3, |
||||||
|
// color: function (params) { |
||||||
|
// let data = adapterOption.series[1].data; |
||||||
|
// return data.itemStyle.color({ dataIndex: params.dataIndex }); |
||||||
|
// }, |
||||||
|
}, |
||||||
|
percentage: { |
||||||
|
align: "left", |
||||||
|
fontSize: titleFontSize * 2.3, |
||||||
|
// color: function (params) { |
||||||
|
// let data = adapterOption.series[1].data; |
||||||
|
// return data.itemStyle.color({ dataIndex: params.dataIndex }); |
||||||
|
// }, |
||||||
|
}, |
||||||
|
}, |
||||||
|
}, |
||||||
|
}, |
||||||
|
series: [ |
||||||
|
{ |
||||||
|
name: "温度监测", |
||||||
|
type: "pie", |
||||||
|
clockWise: false, |
||||||
|
radius: [66, 80], |
||||||
|
center: ["32%", "50%"], |
||||||
|
itemStyle: dataStyle, |
||||||
|
hoverAnimation: false, |
||||||
|
startAngle: 90, |
||||||
|
label: { |
||||||
|
borderRadius: "10", |
||||||
|
}, |
||||||
|
data: [ |
||||||
|
{ |
||||||
|
value: this.chartData1, |
||||||
|
name: "在线数", |
||||||
|
itemStyle: { |
||||||
|
normal: { |
||||||
|
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ |
||||||
|
{ |
||||||
|
offset: 0, |
||||||
|
color: "#e87b4b", |
||||||
|
}, |
||||||
|
{ |
||||||
|
offset: 1, |
||||||
|
color: "#e87b4b", |
||||||
|
}, |
||||||
|
]), |
||||||
|
}, |
||||||
|
}, |
||||||
|
}, |
||||||
|
{ |
||||||
|
value: this.allData, |
||||||
|
name: "", |
||||||
|
tooltip: { |
||||||
|
show: false, |
||||||
|
}, |
||||||
|
itemStyle: placeHolderStyle, |
||||||
|
}, |
||||||
|
], |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: "温度监测", |
||||||
|
type: "pie", |
||||||
|
clockWise: false, |
||||||
|
radius: [36, 50], |
||||||
|
center: ["32%", "50%"], |
||||||
|
itemStyle: dataStyle, |
||||||
|
hoverAnimation: false, |
||||||
|
startAngle: 90, |
||||||
|
data: [ |
||||||
|
{ |
||||||
|
value: this.chartData2, |
||||||
|
name: "离线数", |
||||||
|
itemStyle: { |
||||||
|
normal: { |
||||||
|
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ |
||||||
|
{ |
||||||
|
offset: 0, |
||||||
|
color: "#ffe21e", |
||||||
|
}, |
||||||
|
{ |
||||||
|
offset: 1, |
||||||
|
color: "#ffe21e", |
||||||
|
}, |
||||||
|
]), |
||||||
|
}, |
||||||
|
}, |
||||||
|
}, |
||||||
|
{ |
||||||
|
value: this.allData, |
||||||
|
name: "", |
||||||
|
tooltip: { |
||||||
|
show: false, |
||||||
|
}, |
||||||
|
itemStyle: placeHolderStyle, |
||||||
|
}, |
||||||
|
], |
||||||
|
}, |
||||||
|
], |
||||||
|
}; |
||||||
|
//把配置项给实例对象 |
||||||
|
this.chartInstance.setOption(this.option, true); |
||||||
|
}, |
||||||
|
}, |
||||||
|
}; |
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang="scss" scoped> |
||||||
|
.sys_content { |
||||||
|
padding: 20px; |
||||||
|
.charts { |
||||||
|
width: 100%; |
||||||
|
height: 250px; |
||||||
|
} |
||||||
|
} |
||||||
|
// 媒体查询,适配大于2000px分辨率的大屏样式 |
||||||
|
@media (min-width: 2000px) { |
||||||
|
.sys_content { |
||||||
|
padding: 0.2rem !important; |
||||||
|
.charts { |
||||||
|
width: 100%; |
||||||
|
height: 2.5rem !important; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
</style> |
Loading…
Reference in new issue