FenXiNspUniapp/packDetail/pages/sjdyj/index.vue

961 lines
21 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="container">
<!-- 顶部选项卡 -->
<view class="topScroll">
<scroll-view scroll-x="true" class="scroll">
<view class="scroll-item" v-for="(item,index) in topItems" :key="index" @click="chooseClick(item,index)"
:class="{'scroll-item2':isActive == index}">
{{item.dictLabel}}
<view class="zliebs" v-show="isActive === index">
</view>
</view>
</scroll-view>
</view>
<!-- 监测站告警 -->
<block v-if="isActive == 0">
<scroll-view class="liebiaos" scroll-y="true" :refresher-enabled="true" :refresher-triggered="isRefresher"
@refresherrefresh="refresherrefreshFun" @scrolltolower="lower" v-if="List.length != 0">
<view class="itembox" v-for="(item,index) in List" :key="index">
<view class="itembox_top" v-if="item.fullDeviceName">
<view class="itembox_lef">
<image src="../../static/fz.png" mode=""></image>
<view class="title">
{{item.fullDeviceName}}
</view>
</view>
<view class="itembox_right">
{{item.alertTime}}
</view>
</view>
<view class="itembox_bot">
<block v-if="item.alertContent.length != 0">
<view class="scrolltop">
<view class="tabitem" v-for="(it,i) in tabList" :key="i">
{{it}}
</view>
</view>
<view class="lists_item">
<view class="jczbs">
{{item.itemName?item.itemName:''}}
</view>
<view class="zbz">
{{item.survValue?item.survValue:''}}
</view>
<view class="sbsj" style="color: #FF4242;">
{{item.normalValue?item.normalValue:''}}
</view>
<view class="szqss">
{{item.survUnit?item.survUnit:''}}
</view>
</view>
</block>
</view>
</view>
<!-- 加载更多组件 -->
<view class="load" v-if="List.length > 0">
<uni-load-more :status="loadStatus"></uni-load-more>
</view>
</scroll-view>
<view class="zwsj" v-else>
<view class="inzwsj">
<image src="../../static/zwsj.png" mode="" class="zwsjimg"></image>
<view class="zwsjtext">
暂无数据
</view>
</view>
</view>
</block>
<!-- 异常趋势图 -->
<block v-else-if="isActive == 1">
<view class="liebiaos" v-if="resolt.length>0">
<view class="searchbox">
<view class="uni-px-8 uni-pb-8">
<text>设备选择:</text>
<uni-data-select v-model="value" :localdata="rangeList" @change="change"></uni-data-select>
</view>
<view class="example-body">
<text>时间区间:</text>
<uni-datetime-picker v-model="rangetime" type="date" @maskClick="maskClick" />
</view>
</view>
<!-- 趋势图 -->
<view class="qushicov" v-for="(item,index) in resolt" :key="index">
<text class="quname">{{item.itemName}}</text>
<view class="charts-box">
<qiun-data-charts type="area" :opts="item.chartOpts || opts"
:chartData="{categories: item.categories || [], series: item.chartData || []}"
:enableScroll="true" :ontouch="true" canvas2d />
</view>
</view>
</view>
<view class="zwsj" v-else>
<view class="inzwsj">
<image src="../../static/zwsj.png" mode="" class="zwsjimg"></image>
<view class="zwsjtext">
暂无数据
</view>
</view>
</view>
</block>
</view>
</template>
<script>
import api from "@/api/api"
import configService from '@/common/service/config.service.js';
export default {
data() {
const currentDate = this.getDate({
format: true
})
return {
List: [],
baseUrl: configService.apiUrl,
tabList: ['监测项', '监测值', '阈值范围', '单位'],
array: [],
index: '',
sampTime: '',
deviceNo: '',
allNum: '',
isLastpage: false,
intervalId: null,
loadStatus: 'more', //加载样式more-加载前样式loading-加载中样式nomore-没有数据样式
isLoadMore: false, //是否加载中
show: false,
show1: false,
top: 0,
pageNo: 1,
pageSize: 8,
deleteUrl: '/applet/survMulchRecord/delete',
stationName: '',
stationCode: '',
sampTime: '',
arrays: [],
isRefresher: false, //下拉刷新状态
reload: '',
topItems: [{
dictLabel: '监测站告警'
},
{
dictLabel: '异常趋势图'
}
],
value: 0,
rangeList: [],
isActive: 0,
rangetime: currentDate,
deployId: '',
resolt: [],
chartData: {},
opts: {
color: ["#1890FF", "#FF4242", "#19D58A", "#91CB74", "#FAC858", "#EE6666", "#73C0DE", "#3CA272",
"#FC8452", "#9A60B4", "#ea7ccc"
],
padding: [0, 15, 10, 15],
legend: {
show: true,
position: "top",
float: "right",
itemGap: 10,
margin: 10,
},
enableScroll: false, // 禁用滚动
xAxis: {
disableGrid: true,
scrollShow: false, // 不显示滚动
labelCount: 2, // 只显示2个标签
boundaryGap: 'justify',
// 自定义标签显示逻辑
labelFormatter: (val, i, allLabels) => {
// 只显示第一个和中间的数据
if (i === 0 || i === Math.floor(allLabels.length / 2)) {
return val;
}
return '';
}
},
yAxis: {
gridType: "dash",
dashLength: 2,
showTitle: true,
data: [{
title: '数量',
}],
},
extra: {
area: {
type: "curve",
opacity: 0.2,
addLine: true,
width: 2,
gradient: true,
activeType: "hollow"
},
tooltip: {
textStyle: {
fontSize: 12
},
format: (item, category, index, opts) => {
return `${category}\n${item.seriesName}: ${item.data}`
}
},
markLine: {
data: []
}
}
},
}
},
onLoad() {
this.getList()
this.startTime = this.rangetime
this.endTime = this.rangetime
},
onShow() {
// 页面显示时重新获取数据
this.getList()
},
onReachBottom() {
// 页面触底加载更多 - 备用方案
if (this.isActive === 0) {
this.lower();
}
},
onPullDownRefresh() {
// 页面下拉刷新 - 备用方案
if (this.isActive === 0) {
this.refresherrefreshFun();
} else {
uni.stopPullDownRefresh();
}
},
watch: {
rangetime(newval) {
this.startTime = newval
this.endTime = newval
this.qushiList()
},
},
methods: {
getDate(type) {
const date = new Date();
let year = date.getFullYear();
let month = date.getMonth() + 1;
let day = date.getDate();
if (type === 'start') {
year = year - 10;
} else if (type === 'end') {
year = year + 10;
}
month = month > 9 ? month : '0' + month;
day = day > 9 ? day : '0' + day;
return `${year}-${month}-${day}`;
},
// 下拉刷新被触发
refresherrefreshFun() {
console.log('下拉刷新触发');
this.isRefresher = true;
this.pageNo = 1;
this.deviceNo = '';
this.isLastpage = false;
this.loadStatus = 'more';
this.getList().then(() => {
// 停止下拉刷新
setTimeout(() => {
this.isRefresher = false;
uni.stopPullDownRefresh();
}, 500);
}).catch(() => {
this.isRefresher = false;
uni.stopPullDownRefresh();
});
},
// 切换类型
chooseClick(item, index) {
this.isActive = index;
this.pageNo = 1;
this.deviceNo = '';
this.isLastpage = false;
this.loadStatus = 'more';
this.getList();
if (index == 1) {
this.sbeiList();
}
},
getList() {
return new Promise((resolve, reject) => {
var params = {
pageNo: this.pageNo,
pageSize: this.pageSize
};
uni.showLoading({
title: '加载中'
});
// 根据当前激活的tab设置URL
let url = '';
if (this.isActive == 0) {
url = '/applet/wxclient/alertRecord';
} else if (this.isActive == 1) {
url = '/applet/survPestlightAlert/list';
if (this.deviceNo) {
params.deviceNo = this.deviceNo;
}
}
this.$http.get(url, {
params: params
}).then(res => {
uni.hideLoading();
if (res.data.code == 0) {
var data = res.data.data.records || [];
// 如果是第一页,清空列表;否则追加
if (this.pageNo === 1) {
this.List = data;
} else {
this.List = this.List.concat(data);
}
// 更新分页状态
const total = res.data.data.total || 0;
if (total > 0) {
const totalPages = Math.ceil(total / this.pageSize);
if (this.pageNo >= totalPages || data.length < this.pageSize) {
this.isLastpage = true;
this.loadStatus = 'nomore';
} else {
this.isLastpage = false;
this.loadStatus = 'more';
}
} else {
this.isLastpage = true;
this.loadStatus = 'nomore';
}
} else {
// 接口返回错误
this.isLastpage = true;
this.loadStatus = 'nomore';
}
this.isRefresher = false;
resolve();
}).catch(err => {
uni.hideLoading();
console.error('获取列表失败:', err);
this.isLastpage = true;
this.loadStatus = 'nomore';
this.isRefresher = false;
reject(err);
});
});
},
// 上拉加载更多
lower() {
console.log('上拉加载更多触发');
// 如果是最后一页或正在加载中,直接返回
if (this.isLastpage || this.loadStatus === 'loading') {
return;
}
this.loadStatus = 'loading';
this.pageNo = this.pageNo + 1;
var params = {
pageNo: this.pageNo,
pageSize: this.pageSize
};
// 根据当前激活的tab设置URL
let url = '';
if (this.isActive == 0) {
url = '/applet/wxclient/alertRecord';
} else if (this.isActive == 1) {
url = '/applet/survPestlightAlert/list';
if (this.deviceNo) {
params.deviceNo = this.deviceNo;
}
}
this.$http.get(url, {
params: params
}).then(res => {
if (res.data.code == 0) {
var data = res.data.data.records || [];
this.List = this.List.concat(data);
// 更新分页状态
const total = res.data.data.total || 0;
if (total > 0) {
const totalPages = Math.ceil(total / this.pageSize);
if (this.pageNo >= totalPages || data.length < this.pageSize) {
this.isLastpage = true;
this.loadStatus = 'nomore';
} else {
this.isLastpage = false;
this.loadStatus = 'more';
}
} else {
this.isLastpage = true;
this.loadStatus = 'nomore';
}
} else {
this.isLastpage = true;
this.loadStatus = 'nomore';
this.pageNo = this.pageNo - 1; // 加载失败时回退页码
}
}).catch(err => {
console.error('加载更多失败:', err);
this.loadStatus = 'more';
this.pageNo = this.pageNo - 1; // 加载失败时回退页码
});
},
changenr() {
this.pageNo = 1;
this.getList();
},
// 趋势图接口
async qushiList() {
try {
const data = {
deployId: this.deployId,
startTime: this.startTime,
endTime: this.endTime,
};
const res = await this.$http.post('/applet/survAlertRecord/alertSummary', data);
if (res.data.code === 0) {
let ovelit = res.data.data;
this.resolt = ovelit.itemList.map(item => {
return {
...item,
data: ovelit.dataMap[item.entity] || []
};
});
this.timeList = ovelit.timeList || [];
this.getServerData(this.resolt);
}
} catch (error) {
console.error("获取趋势图数据失败", error);
}
},
// 设备列表
async sbeiList() {
try {
uni.showLoading({
title: '加载中'
});
const res = await this.$http.get('/applet/survDeviceDeploy/deviceList?stationCode=');
if (res.data.code === 0) {
this.rangeList = res.data.data.map((lit, index) => {
return {
"value": index,
"text": lit.deployDes,
"id": lit.id,
};
});
if (this.rangeList.length > 0) {
this.deployId = this.rangeList[this.value].id;
await this.qushiList();
}
}
uni.hideLoading();
} catch (error) {
console.error("获取设备列表失败", error);
uni.hideLoading();
}
},
// 选择deployid
change(e) {
this.deployId = this.rangeList[this.value].id;
this.sbeiList();
},
// 选择日期范围
maskClick(e) {
this.rangetime = e;
},
// 处理图表数据
getServerData(val) {
const chartDataList = val.map(item => {
const series = [];
// 处理主要数据
const mainData = (item.data.slice(0, 50) || Array(this.timeList?.length || 0).fill(0))
.map(value => Number(value) || 0);
const highValNum = item.highVal ? Number(item.highVal) || 0 : null;
const lowValNum = item.lowVal ? Number(item.lowVal) || 0 : null;
// 正常数据线 - 实线
series.push({
name: item.itemName,
data: mainData,
color: "#1890FF",
lineType: "solid",
pointShape: "circle",
show: true
});
// 最高阈值线 - 虚线
if (highValNum !== null) {
series.push({
name: `最高阈值: ${highValNum}`,
data: Array(this.timeList?.length || 0).fill(highValNum),
color: "#FF4242",
lineType: "dashed", // 虚线
pointShape: "none", // 不显示点
show: true,
});
}
// 最低阈值线 - 虚线
if (lowValNum !== null) {
series.push({
name: `最低阈值: ${lowValNum}`,
data: Array(this.timeList?.length || 0).fill(lowValNum),
color: "#19D58A",
lineType: "dashed", // 虚线
pointShape: "none", // 不显示点
show: true,
});
}
return {
categories: this.timeList.slice(0, 50) || [],
series: series,
chartOpts: this.getChartOpts(item.itemName, item.unit)
};
});
// 更新resolt数据
this.resolt = this.resolt.map((item, index) => {
return {
...item,
chartData: chartDataList[index] ? chartDataList[index].series : [],
categories: chartDataList[index] ? chartDataList[index].categories : [],
chartOpts: chartDataList[index] ? chartDataList[index].chartOpts : this.getChartOpts(item.itemName, item.unit)
};
});
console.log("处理后的趋势图数据", this.resolt);
},
// 获取图表配置
getChartOpts(itemName, unit) {
return {
color: ["#1890FF", "#FF4242", "#19D58A", "#91CB74", "#FAC858", "#EE6666", "#73C0DE", "#3CA272",
"#FC8452", "#9A60B4", "#ea7ccc"
],
padding: [0, 15, 10, 5],
legend: {
show: true,
position: "top",
float: "right",
itemGap: 10,
margin: 10,
},
enableScroll: false, // 禁用滚动,显示所有数据
dataLabel: false,
xAxis: {
disableGrid: true,
scrollShow: false, // 不显示滚动条
labelCount: 3, // 设置显示3个标签对应我们要显示的3个点
boundaryGap: 'justify',
// 自定义标签显示:显示第一个、中间和倒数第三个数据
labelFormatter: (val, i, allLabels) => {
if (!allLabels || allLabels.length === 0) {
return val;
}
const total = allLabels.length;
// 1. 第一个标签
if (i === 0) {
return val;
}
// 2. 中间标签
const middleIndex = Math.floor(total / 2);
if (total % 2 === 0 && i === middleIndex - 1) {
// 如果是偶数个,显示中间两个中的前一个
return val;
} else if (i === middleIndex) {
// 如果是奇数个,显示正中间
return val;
}
// 3. 倒数第三个标签
// 确保有足够的数据点
if (total >= 3) {
const thirdLastIndex = total - 3;
if (i === thirdLastIndex) {
return val;
}
}
// 如果数据少于3个显示最后一个
else if (i === total - 1) {
return val;
}
return ''; // 其他标签返回空字符串
}
},
yAxis: {
gridType: "dash",
dashLength: 2,
showTitle: true,
data: [{
title: unit || '单位',
}],
},
extra: {
area: {
type: "curve",
opacity: 0.2,
addLine: true,
width: 2,
gradient: true,
activeType: "hollow"
},
tooltip: {
textStyle: {
fontSize: 12
},
format: (item, category, index, opts) => {
return `${category}\n${item.seriesName}: ${item.data}`
}
},
markLine: {
},
line: {
width: 2,
smooth: true
}
}
};
},
// 自定义图例渲染(如果需要)
customLegendRender() {
// 如果uCharts的图例样式不满足需求可以考虑使用自定义的图例组件
// 这里可以返回一个自定义的图例HTML或组件
}
}
}
</script>
<style lang="scss">
page {
height: 100%;
background: #fff;
/* 确保页面可以滚动 */
overflow: auto;
}
.container {
min-height: 100%;
/* 改为 min-height */
padding-bottom: 20rpx;
}
.searchbox {
height: 148rpx;
padding: 15rpx 30rpx;
background-color: white;
position: relative;
display: flex;
justify-content: space-between;
}
.search_input {
border: none;
height: 60rpx;
width: 86%;
font-size: 24rpx;
border-radius: 30rpx;
background-color: #F6F6F6;
padding-left: 50rpx;
}
.searchbox image {
width: 32rpx;
height: 32rpx;
position: absolute;
left: 40rpx;
top: 35%;
z-index: 99;
}
.searchbutton {
width: 10%;
height: 60rpx;
font-size: 26rpx;
text-align: center;
line-height: 60rpx;
}
.itembox {
background-color: white;
padding: 10rpx 30rpx;
margin-top: 20rpx;
border-bottom: 20rpx solid #f3f3f3;
}
.itembox:first-child {
margin-top: 0;
border-top: 20rpx solid #f3f3f3;
}
.itembox_top {
display: flex;
align-items: center;
justify-content: space-between;
padding: 20rpx 0;
border-bottom: 2rpx solid #e4e4e4;
}
.itembox_lef image {
width: 40rpx;
height: 40rpx;
margin-right: 14rpx;
}
.itembox_lef {
display: flex;
align-items: center;
font-weight: 500;
width: 63%;
}
.title {
font-weight: bold;
}
.load {
height: 100rpx;
line-height: 100rpx;
text-align: center;
color: #c6c6c6;
}
.zwsj {
width: 100%;
display: flex;
padding: 60% 170rpx 0;
}
.inzwsj {
width: 100%;
}
.zwsjimg {
width: 100%;
height: 224rpx;
margin-bottom: 37rpx;
}
.zwsjtext {
width: 100%;
font-size: 26rpx;
font-family: Source Han Sans SC;
font-weight: 400;
color: #999999;
line-height: 31rpx;
text-align: center;
}
.topScroll {
width: 100%;
height: 85rpx;
background-color: #fff;
border-bottom: 1rpx solid #ededed;
position: sticky;
top: 0;
z-index: 999;
}
.scroll {
height: 85rpx;
display: flex;
white-space: nowrap;
justify-content: space-between;
padding-top: 12rpx;
background: #fff;
}
.scroll-item {
width: 50%;
text-align: center;
display: inline-block;
font-size: 28rpx;
font-family: Source Han Sans SC;
}
.scroll-item2 {
font-size: 30rpx;
font-family: Source Han Sans SC;
color: #0F6EFF;
}
.zliebs {
width: 100rpx;
height: 4rpx;
background-color: #0F6EFF;
margin: 12rpx auto 0;
border-radius: 20rpx;
}
.lists_item {
padding: 0rpx 0rpx 16rpx 0rpx;
box-sizing: border-box;
display: flex;
}
.lists_item {
padding-top: 16rpx;
}
.jczbs {
width: 32%;
font-size: 24rpx;
font-family: Source Han Sans SC;
font-weight: 400;
color: #667482;
text-align: center;
}
.zbz {
width: 27%;
font-size: 24rpx;
font-family: DIN Next LT Pro;
font-weight: 400;
text-align: center;
}
.sbsj {
font-size: 24rpx;
font-family: Source Han Sans SC;
font-weight: 400;
color: #667482;
width: 23%;
text-align: center;
}
.zximg {
width: 30rpx;
height: 30rpx;
margin-left: 6rpx;
}
.szqss {
flex: 1;
font-size: 24rpx;
font-family: Source Han Sans SC;
font-weight: 400;
text-align: center;
}
.scrolltop {
padding: 20rpx 0rpx 16rpx 0rpx;
display: flex;
justify-content: space-between;
border-bottom: 2rpx solid #F6F8FB;
width: 100%;
}
.tabitem {
font-size: 26rpx;
font-family: Source Han Sans SC;
font-weight: 500;
color: #2F3841;
display: inline-block;
padding-bottom: 8rpx;
text-align: center;
}
.tabitem:first-child {
width: 32%;
text-align: center;
}
.tabitem:nth-child(2) {
width: 27%;
text-align: center;
}
.tabitem:nth-child(3) {
width: 23%;
text-align: center;
}
.tabitem:nth-child(4) {
flex: 1;
text-align: center;
}
.itembox_right {
font-size: 26rpx;
}
.charts-box {
width: 100%;
height: 400rpx;
/* 适当增加高度 */
overflow-x: auto;
/* 允许横向滚动 */
display: block;
}
.qushicov {
margin-bottom: 60rpx;
overflow: hidden;
.quname {
display: block;
text-align: center;
line-height: 60rpx;
font-weight: bold;
font-size: 28rpx;
margin-bottom: 10rpx;
}
}
/* 确保列表容器有固定高度才能滚动 */
.liebiaos {
height: calc(100vh - 100rpx);
/* 根据你的实际布局调整 */
}
.load {
padding: 20rpx 0;
text-align: center;
}
.zwsj {
height: calc(100vh - 100rpx);
display: flex;
align-items: center;
justify-content: center;
}
.inzwsj {
text-align: center;
}
.zwsjimg {
width: 200rpx;
height: 200rpx;
}
.zwsjtext {
font-size: 28rpx;
color: #999;
margin-top: 20rpx;
}
</style>