FenXiNspUniapp/packDetail/pages/sjdyj/index.vue

970 lines
23 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: ["#c3c3c3","#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方法
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: "#c3c3c3",
lineType: "solid",
pointShape: "circle",
show: true
});
// 最高阈值线 - 尝试不同方式设置虚线
if (highValNum !== null) {
series.push({
name: `最高阈值: ${highValNum}`,
data: Array(this.timeList?.length || 0).fill(highValNum),
color: "#FF4242",
// 尝试不同的虚线设置方式
lineType: "dash", // 或者尝试 "dashed", "dot", "dashdot"
dashLength: 10, // 设置虚线段的长度
gapLength: 5, // 设置间隔的长度
pointShape: "none",
show: true,
// 使用自定义样式
custom: {
lineDash: [10, 5] // 数组格式:[线段长度, 间隔长度]
}
});
}
// 最低阈值线
if (lowValNum !== null) {
series.push({
name: `最低阈值: ${lowValNum}`,
data: Array(this.timeList?.length || 0).fill(lowValNum),
color: "#19D58A",
lineType: "dash",
dashLength: 10,
gapLength: 5,
pointShape: "none",
show: true,
custom: {
lineDash: [10, 5]
}
});
}
return {
categories: this.timeList.slice(0, 50) || [],
series: series,
chartOpts: this.getChartOpts(item.itemName, item.unit)
};
});
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)
};
});
},
// 修改getChartOpts方法添加对虚线的支持
getChartOpts(itemName, unit) {
return {
color: ["#c3c3c3", "#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,
boundaryGap: 'justify',
labelFormatter: (val, i, allLabels) => {
if (!allLabels || allLabels.length === 0) return val;
const total = allLabels.length;
if (i === 0 || i === Math.floor(total / 2) || i === total - 3) {
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}`
}
},
line: {
width: 2,
smooth: true,
// 为所有线条添加虚线配置
style: "dash", // 默认样式
dashLength: 8, // 虚线长度
gapLength: 4, // 间隔长度
lineCap: "round" // 线帽样式
},
// 添加自定义渲染回调
render: {
series: {
line: (canvas, config, series, index) => {
// 自定义线条渲染函数
const ctx = canvas.getContext('2d');
ctx.save();
// 根据系列索引判断是否为阈值线索引1和2
if (index === 1 || index === 2) {
// 设置虚线
ctx.setLineDash([10, 5]); // 10px线段5px间隔
ctx.lineDashOffset = 0;
} else {
// 实线
ctx.setLineDash([]);
}
// 调用原始绘制逻辑
config.chart.option.extra.render.series.line.call(this, canvas, config, series, index);
ctx.restore();
}
}
}
}
};
},
// 自定义图例渲染(如果需要)
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>