<template>
<view class="page">
<guogong-navbar :shadow="false" content-background='transparent'></guogong-navbar>
<image :src="STATIC_URL + 'iot/param-icon.png'" style="width: 220rpx;height: auto;position: fixed;right: 32rpx;z-index: -1" :style="{top: CustomBar + 'px'}" mode="widthFix"></image>
<!-- <view class="param_title">{{ pageData.deviceName }}</view>-->
<view class="param_title">平行反应仪详情</view>
<view class="param_detail_item" v-if="pageData">
<view class="flex align-center justify-between">
<!-- <view class="param_detail_title">{{pageData.stationName}}</view>-->
<view class="param_detail_title">通道#1</view>
<view @tap.stop="handleJump" :data-url="`/pages/device/paramSetting?id=${props.id}&deviceId=${props.deviceId}`">
<uni-icons type="more-filled" size="28rpx" style="transform: rotate(90deg)" color="var(--font-color-content)"></uni-icons>
</view>
</view>
<view class="flex align-start u-m-t-32">
<image :src="STATIC_URL + 'iot/param-icon.png'" style="width: 160rpx;height: auto" mode="widthFix"></image>
<view class="param-area">
<template v-for="itemP in pageData.outParametersRunningRecordsVOList" :key="itemP.id">
<view class="flex align-center" v-if="itemP.displayType === '4'" style="margin-left: 24rpx;margin-top: 12rpx">
{{ itemP.parameterName }}:<image :src="STATIC_URL + (itemP.parameterValue === '1' ? 'iot/warning.png' : 'iot/normal.png')" style="width: 40rpx;height: 40rpx"></image>
</view>
</template>
</view>
</view>
<view class="monitor-data">
<!-- 只展示动态的 dataType为2 -->
<!-- 左 -->
<view class="monitor-data-col">
<view class="monitor-data-item" v-for="(item, index) in pageData.left" :key="'inner' + index">
<view class="monitor-data-row">
<image :src="STATIC_URL + 'iot/temp.png'" style="width: 33%;height: auto;margin-right: 20rpx;aspect-ratio: 1 / 1;" alt="" v-if="item.capabilityIconName==='temp.png'"></image>
<image :src="STATIC_URL + 'iot/rpm.png'" style="width: 33%;height: auto;margin-right: 20rpx;aspect-ratio: 1 / 1;" alt="" v-if="item.capabilityIconName==='rpm.png'"></image>
<image :src="STATIC_URL + 'iot/pressure.png'" style="width: 33%;height: auto;margin-right: 20rpx;aspect-ratio: 1 / 1;" alt="" v-if="item.capabilityIconName==='pressure.png'"></image>
<view class="monitor-data-text">
<view class="monitor-data-title">{{ item.parameterName }}</view>
<view class="monitor-data-content">{{ item.parameterValue }}{{ item.unit || '' }}</view>
</view>
</view>
<!-- 展示设定的静态数据 dataType为1 双方能力id相同 -->
<template v-for="(itemS, indexS) in pageData.innerParametersRunningRecordsVOList">
<view class="monitor-data-setting" :key="'innerStatic' + indexS" v-if="itemS.displayType !== '3' && itemS.dataType === '1' && itemS.capabilityId === item.capabilityId">
{{ itemS.parameterName }}:{{ itemS.parameterValue }}{{ item.unit || '' }}
</view>
</template>
<!-- 展示按钮数据 双方能力id相同 displayType:展示类型【1 文本 2 数值 3 开关 4 状态】 -->
<template v-for="(itemS, indexS) in pageData.innerParametersRunningRecordsVOList">
<view class="monitor-data-switch" :key="'innerSwitch' + indexS" v-if="itemS.displayType === '3' && itemS.capabilityId === item.capabilityId">
<text style="width: 120rpx;">{{ itemS.parameterName }}:</text>
<switch style="transform: scale(0.7)" @change="switchChange($event, itemS)" disabled />
</view>
</template>
</view>
</view>
<!-- 右 -->
<view class="monitor-data-col">
<view class="monitor-data-item" v-for="(item, index) in pageData.right" :key="'inner' + index">
<view class="monitor-data-row">
<image :src="STATIC_URL + 'iot/temp.png'" style="width: 33%;height: auto;margin-right: 20rpx;aspect-ratio: 1 / 1;" alt="" v-if="item.capabilityIconName==='temp.png'"></image>
<image :src="STATIC_URL + 'iot/rpm.png'" style="width: 33%;height: auto;margin-right: 20rpx;aspect-ratio: 1 / 1;" alt="" v-if="item.capabilityIconName==='rpm.png'"></image>
<image :src="STATIC_URL + 'iot/pressure.png'" style="width: 33%;height: auto;margin-right: 20rpx;aspect-ratio: 1 / 1;" alt="" v-if="item.capabilityIconName==='pressure.png'"></image>
<view class="monitor-data-text">
<view class="monitor-data-title">{{ item.parameterName }}</view>
<view class="monitor-data-content">{{ item.parameterValue }}{{ item.unit || '' }}</view>
</view>
</view>
<!-- 展示设定的静态数据 dataType为1 双方能力id相同 -->
<template v-for="(itemS, indexS) in pageData.innerParametersRunningRecordsVOList">
<view class="monitor-data-setting" :key="'innerStatic' + indexS" v-if="itemS.displayType !== '3' && itemS.dataType === '1' && itemS.capabilityId === item.capabilityId">
{{ itemS.parameterName }}:{{ itemS.parameterValue }}{{ item.unit || '' }}
</view>
</template>
<!-- 展示按钮数据 双方能力id相同 displayType:展示类型【1 文本 2 数值 3 开关 4 状态】 -->
<template v-for="(itemS, indexS) in pageData.innerParametersRunningRecordsVOList">
<view class="monitor-data-switch" :key="'innerSwitch' + indexS" v-if="itemS.displayType === '3' && itemS.capabilityId === item.capabilityId">
<text style="width: 120rpx;">{{ itemS.parameterName }}:</text>
<switch style="transform: scale(0.7)" @change="switchChange($event, itemS)" disabled />
</view>
</template>
</view>
</view>
</view>
</view>
<view class="echart-container" v-if="eChartArr" v-for="(item, index) in eChartArr" :key="item.parameterId">
<view class="echart-title">{{ item.parameterName }}</view>
<image :src="STATIC_URL + 'iot/full-screen.png'" style="width: 48rpx;height: 48rpx;position: absolute;right: 24rpx;top: 24rpx" @tap="handleJump" :data-url="`/pages/device/eChartPage?id=${item.parameterId}&deviceId=${props.deviceId}`"></image>
<l-echart ref="myChartRef" :beforeDelay='1000' :id="'chart' + index" />
</view>
</view>
</template>
<script setup>
import { onLoad, onShow, onHide } from "@dcloudio/uni-app";
import api from '@/api';
import {inject, ref, defineProps, nextTick, markRaw, onBeforeUnmount} from "vue";
import * as echarts from '@/pages/cockpit/js/echarts.esm.min.js';
import { dayjs } from '@/uni_modules/iRainna-dayjs/js_sdk/dayjs.min.js';
import {handleJump} from "@/utils/utils";
const $utils = inject('$utils');
const $message = inject('$message');
const props = defineProps({
title: {
type: String,
default: ''
},
id: {
type: String,
default: ''
},
deviceId: {
type: String,
default: ''
}
})
onLoad(()=>{
});
const myChartRef = ref(null)// ref对象
const myChart = []; // chart实例对象
const option = (xData = ['2023-10-11', '2024-10-12', '2025-10-13', '2026-10-14'], yData = [{name: '单位', data: [1211, 2122, 1333, 3444]}, {name: '百分比', data: [2230, 2220, 2890, 2100]}]) => {
return {
legend: {
data: yData.map(item=>{
return item.name
}),
textStyle: {
color: '#333' // 设置图例文字颜色为红色
},
right: 0
},
// 设置
tooltip: {
trigger: "item", // 触发类型 axis:坐标轴触发 item:数据项图形触发
backgroundColor: "rgba(0,0,0,0.2)", // 设置背景颜色
textStyle: {
color: "#fff", // 设置文字颜色
fontWeight: "bold", // 设置文字字体加粗
},
showContent: true, //显示提示框浮层
axisPointer: {
type: "line", // 设置为十字准星指示器
snap: true, // 当前值对齐
lineStyle: {
color: "#11a9ff", // 设置虚线颜色
type: "dashed",
width: 2,
},
// 文字样式
label: {
show: true,
formatter: (params) => {
return dayjs(params.value).format("MM-DD");
},
backgroundColor: "#FFC000", // 设置标签背景颜色
textStyle: {
color: "#fff", // 设置标签文字颜色
},
with: "32px",
padding: [4, 6], // 设置标签内边距
borderRadius: 4, // 设置标签圆角弧度
},
crossStyle: {
type: "dashed", // 十字准星的线条类型为虚线
},
},
},
xAxis: {
type: "category",
data: xData, // x轴数据,根据实际数据进行修改
axisLabel: {
interval: "auto", // 根据数据长度计算间隔
formatter: (value) => {
return dayjs(value).format("HH:mm:ss");
},
},
boundaryGap: false, // 去除轴与折线图之间的间隙
axisLine: {
show: true,
lineStyle: {
color: "#86909C",
},
},
// splitLine: {
// show: true, // 显示刻度线
// lineStyle: {
// type: "dashed", // 刻度线类型为虚线
// color: "rgb(134,144,156)", // 刻度线颜色
// },
// },
axisTick: {
show: false
},
},
yAxis: {
type: "value",
nameTextStyle: {
color: "#86909C",
nameLocation: "start",
},
axisLine: {
lineStyle: {
color: "#86909C",
},
},
axisLabel: {
show: true,
interval: "auto",
},
splitLine: {
show: true, // 显示刻度线
lineStyle: {
type: "dashed", // 刻度线类型为虚线
color: "rgb(134,144,156)", // 刻度线颜色
},
},
animationDuration: 1000,// 动画时间
},
series: yData.map((item)=>{
return {
type: "line",
showSymbol: true, // 显示拐点
symbolSize: 8, // 拐点大小 --- 用于聚焦时候的拐点大小
data: item.data, // y轴数据,根据实际数据进行修改
name: item.name
}
}),
grid: {
left: "14%",
right: "12%",
top: "20%",
bottom: "12%",
},
}
}
const showEChart = ref(false)
// 初始化图标
const initCharts = () => {
nextTick(()=>{
myChartRef.value.forEach(async (item, index) => {
if(myChart.length < myChartRef.value.length){
myChart.push(await item.init(echarts));
}
let yData = eChartArr.value[index].stationRunningRecordsVOList.map((itemD, index) => {return {
name: itemD.stationName,
type: 'line',
data: itemD.parametersRunningRecordsVOList.map((itemP, index) => {return itemP.parameterValue})
}});
myChart[index].setOption(option(eChartArr.value[index].xlabel, yData));
// renderCharts(option(eChartArr.value[index].xlabel, yData), myChart[index]);
});
})
showEChart.value = true;
}
// 渲染图标/更新图标
const renderCharts = (options, item) => {
item.setOption(options);
}
// 当前选中的通道
const pageData = ref(null);
// 通道列表
const pageList = ref(null);
let interval = null;
const initPage = () => {
if(interval){
return;
}
getLastestRecord();
getEChartData();
interval = setInterval(()=>{
getLastestRecord();
getEChartData();
}, 2000);
}
onShow(()=>{
initPage();
});
onHide(()=>{
if(interval){
clearInterval(interval);
interval = null;
}
});
onBeforeUnmount(()=>{
if(interval){
clearInterval(interval);
interval = null;
}
});
const getLastestRecord = async () => {
let res = await api.iot.getLatestRunningRecord(props.deviceId);
if(res.code !== 200){
$message.info(res.message);
return;
}
// 分割左右数组,用于展示瀑布流
res.result.forEach(item=>{
item.block = [];
item.right = [];
item.left = [];
item.innerParametersRunningRecordsVOList.forEach(item2=>{
if(item2.dataType === '2'){
item.block.push(item2)
if(item.block.length%2>0){
item.left.push(item2);
}else{
item.right.push(item2);
}
}
if(item2.displayType === '3'){
item2.parameterValue = item2.parameterValue !== '0';
}
});
});
pageList.value = res.result;
pageData.value = res.result.find(item=>item.stationId === props.id);
}
const eChartArr = ref(null);
const getEChartData = async () => {
let res = await api.iot.getRunningRecord({
deviceId: props.deviceId,
taskId: '',
latestCount: 100,
startTime: '',
endTime: ''
});
if(res.code !== 200){
$message.info(res.message);
return;
}
eChartArr.value = res.result;
nextTick(()=>{
initCharts();
})
}
const switchChange = (e, item) => {
item.parameterValue = e.detail.value
}
</script>
<style scoped lang="scss">
// 容器
.echart-container {
position: relative;
height: 500rpx;
background-size: 100% 100%;
margin-top: 32rpx;
box-shadow: 0 8rpx 20rpx 0 rgba(0, 0, 0, 0.1);
border-radius: 16rpx;
width: calc(100% - 64rpx);
background: url(image-path('iot/param-bg.png')) no-repeat;
background-size: contain;
background-color: #fff;
padding: 64rpx 32rpx;
.echart-title{
position: absolute;
line-height: 1.4;
font-size: 36rpx;
font-weight: bold;
margin-top: -32rpx;
}
}
.monitor-data-switch{
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
height: 76rpx;
color: #3D3D3D;
font-size: 26rpx;
line-height: 1.4;
border-radius: 4rpx;
background: #ECF5FF;
margin-bottom: 20rpx;
padding: 0 20rpx;
}
.monitor-data-setting{
color: var(--font-color-main);
font-size: 26rpx;
line-height: 1.4;
margin: 0 auto 30rpx auto;
font-weight: normal;
}
.monitor-data-title{
color: var(--font-color-main);
font-size: 24rpx;
line-height: 1.4;
font-weight: bold;
}
.monitor-data-content{
color: var(--theme);
font-size: 28rpx;
line-height: 1.4;
font-weight: bold;
margin-top: 12rpx;
}
.monitor-data-text{
display: flex;
flex-direction: column;
}
.monitor-data-row{
display: flex;
flex-direction: row;
align-items: center;
margin-bottom: 30rpx;
width: 100%;
}
.monitor-data-item{
border-radius: 16rpx;
border: 1px solid #D6D6D6;
display: flex;
flex-direction: column;
align-items: center;
padding: 32rpx 24rpx 12rpx 24rpx;
margin-bottom: 24rpx;
}
.monitor-data{
display: flex;
flex-direction: row;
justify-content: space-between;
width: 100%;
.monitor-data-col{
width: calc(50% - 12rpx);
display: flex;
flex-direction: column;
}
}
.param-area{
display: flex;
flex-direction: row;
align-items: center;
flex-wrap: wrap;
width: calc(100% - 160rpx);
font-size: 28rpx;
color: var(--font-color-content);
}
.param_detail_title{
font-weight: bold;
font-size: 32rpx;
line-height: 1.4;
color: var(--font-color-main);
}
.param_detail_item{
box-shadow: 0 8rpx 20rpx 0 rgba(0, 0, 0, 0.1);
border-radius: 16rpx;
width: calc(100% - 64rpx);
background: url(image-path('iot/param-bg.png')) no-repeat;
background-size: contain;
background-color: #fff;
padding: 24rpx 32rpx;
margin-top: 64rpx;
}
.param_title{
color: var(--theme);
font-size: 56rpx;
font-weight: bold;
line-height: 1.4;
width: 100%;
padding: 0 64rpx;
font-style: italic;
margin-top: 42rpx;
}
.page {
width: 100%;
min-height: 100%;
position: absolute;
background: url(image-path('iot/param-bg.png')) no-repeat;
background-size: contain;
display: flex;
flex-direction: column;
align-items: center;
z-index: 0;
}
</style>

- 发布:2025-08-28 11:13
- 更新:2025-08-28 11:17
- 阅读:11
产品分类: uniapp/App
PC开发环境操作系统: Windows
PC开发环境操作系统版本号: win11
HBuilderX类型: 正式
HBuilderX版本号: 4.76
手机系统: Android
手机系统版本号: Android 15
手机厂商: 华为
手机机型: nova13pro
页面类型: vue
vue版本: vue3
打包方式: 云端
项目创建方式: HBuilderX
示例代码:
操作步骤:
真机调试成功后,后台划掉app并重新进入
真机调试成功后,后台划掉app并重新进入
预期结果:
正常显示图表
正常显示图表
实际结果:
无法正常显示,也不报错
无法正常显示,也不报错
bug描述:
h5显示一切正常,到了APP调试就犯病了
刚刷进去就是好的,一旦从后台划掉App再进去就不显示图表了,而且控制台不报错
数据量大概是四个图表,每个图表120个点位
1 个回复
DCloud_UNI_JBB
三方插件的相关问题可以反馈到插件社区,或者联系插件作者解决