<template>
|
<view>
|
<view class="card-box center dynamic shadow">
|
<view class="title-box margin-bottom-sm">
|
<view style="width: 100vw;" class="left justify-between">
|
<view class="flex align-center">
|
<uni-text class="cuIcon-titles text-blue"></uni-text>
|
<view class="title">最近报警</view>
|
</view>
|
<view>
|
<text class="text-blue text-sm">更多></text>
|
</view>
|
|
</view>
|
|
</view>
|
|
|
<view class="borderTop">
|
<view class="h-table">
|
<view class="h-tr h-tr-2 ">
|
<view class="h-td">机台</view>
|
<view class="h-td">故障</view>
|
<view class="h-td">时间</view>
|
<view class="h-td">类型</view>
|
</view>
|
<view class="h-tr h-tr-2" v-for="(item,index) in faultList">
|
<view class="h-td">{{item.equName}}</view>
|
<view class="h-td text-ellipsis">{{item.faultName}}</view>
|
<view class="h-td text-ellipsis">{{item.faultTimeStr}}</view>
|
<view class="h-td">{{item.faultType===1?'故障':'告警'}}</view>
|
</view>
|
|
</view>
|
|
</view>
|
|
|
</view>
|
|
<view class="card-box center dynamic shadow">
|
<view class="title-box margin-bottom-sm">
|
<view style="width: 100vw;" class="left justify-between">
|
<view class="flex align-center">
|
<uni-text class="cuIcon-titles text-blue"></uni-text>
|
<view class="title">报警统计</view>
|
</view>
|
<view>
|
<text class="text-gray text-sm"></text>
|
</view>
|
|
</view>
|
|
</view>
|
|
|
<view class="chartsMain" style="height: 400rpx;">
|
<!-- <qiun-data-charts type="mount" :opts="opts" :ontouch='true' :animation="true" :chartData="mountData" /> -->
|
<qiun-data-charts canvasId="chat1" type="column" :errorMessage="errorMessage1"
|
:opts="opts" :ontouch='true' :animation="true" :chartData="statisData" />
|
|
</view>
|
</view>
|
|
|
<view class="card-box center dynamic shadow">
|
<view class="title-box margin-bottom-sm">
|
<view style="width: 100vw;" class="left justify-between">
|
<view class="flex align-center">
|
<uni-text class="cuIcon-titles text-blue"></uni-text>
|
<view class="title">报警对比</view>
|
</view>
|
<view>
|
<text class="text-gray text-sm"></text>
|
</view>
|
|
</view>
|
|
</view>
|
|
<view class="chartsMain">
|
<qiun-data-charts canvasId="chat2" type="pie" :errorMessage="errorMessage2"
|
:opts="optsPie" :ontouch='true' :animation="true" :chartData="pieData" />
|
|
</view>
|
</view>
|
|
|
|
<view class="card-box center dynamic shadow">
|
<view class="title-box margin-bottom-sm">
|
<view style="width: 100vw;" class="left justify-between">
|
<view class="flex align-center">
|
<uni-text class="cuIcon-titles text-blue"></uni-text>
|
<view class="title">报警频率</view>
|
</view>
|
<view>
|
<text class="text-gray text-sm"></text>
|
</view>
|
|
</view>
|
|
</view>
|
|
|
<view class="chartsMain" style="height: 500rpx;">
|
<!-- <qiun-data-charts type="mount" :opts="{extra:{mount:{type:'mount',widthRatio:1.5}}}"
|
:chartData="Mount" /> -->
|
<qiun-data-charts canvasId="chat3" type="word" :errorMessage="errorMessage3"
|
:chartData="wordData" />
|
</view>
|
</view>
|
|
<view class="card-box bot dynamic shadow">
|
<view class="title-box margin-bottom-sm">
|
<view style="width: 100vw;" class="left justify-between">
|
<view class="flex align-center">
|
<uni-text class="cuIcon-titles text-blue"></uni-text>
|
<view class="title">报警分析</view>
|
</view>
|
<view>
|
<text class="text-gray text-sm"></text>
|
</view>
|
|
</view>
|
|
</view>
|
|
|
<view class="chartsMain" style="height: 500rpx;">
|
<qiun-data-charts canvasId="chat4" type="line" :opts="optsStep"
|
:errorMessage="errorMessage4" :ontouch='true' :animation="true" :chartData="statisData" />
|
|
<!-- <qiun-data-charts type="radar" :opts="optsRadar" :chartData="dataRadar" /> -->
|
</view>
|
</view>
|
|
|
</view>
|
|
|
</template>
|
|
<script>
|
import dayjs from 'dayjs'
|
export default {
|
data() {
|
return {
|
"PieA": {
|
"series": [{
|
"data": [
|
|
]
|
}]
|
},
|
errorMessage1: "",
|
errorMessage2: "",
|
errorMessage3: "",
|
errorMessage4: "",
|
faultList: [],
|
pieData: {
|
"series": [{
|
"data": []
|
}]
|
},
|
statisData: {
|
series: [],
|
categories: []
|
},
|
wordData: {
|
series: []
|
},
|
optsStep: {
|
enableScroll: true,
|
xAxis: {
|
marginTop: 10,
|
itemCount: 8,
|
rotateLabel: true
|
},
|
extra: {
|
line: {
|
type: 'step'
|
}
|
}
|
},
|
opts: {
|
enableScroll: true,
|
xAxis: {
|
marginTop: 10,
|
itemCount: 8,
|
rotateLabel: true
|
},
|
legend: {
|
show: false
|
},
|
yAxis: {
|
data: [{
|
min: 0
|
}]
|
},
|
extra: {
|
column: {
|
width: 12,
|
seriesGap: 5,
|
barBorderRadius: [6, 6, 6, 6]
|
}
|
}
|
},
|
optsPie: {
|
padding: [5, 5, 5, 5],
|
legend: {
|
show: false
|
},
|
fontSize: 12,
|
extra: {
|
pie: {
|
activeOpacity: 0.5,
|
activeRadius: 10,
|
offsetAngle: 0,
|
labelWidth: 1,
|
border: true,
|
borderWidth: 3,
|
borderColor: "#FFFFFF",
|
linearType: "custom"
|
}
|
}
|
},
|
|
}
|
},
|
mounted() {
|
setTimeout(() => {
|
this.init()
|
}, 300)
|
},
|
methods: {
|
init() {
|
// 获取N天前的0点0分0秒
|
let daysAgo = dayjs().subtract(3, 'day').startOf('day').format('YYYY-MM-DD HH:mm:ss');
|
// 获取今天的23点59分59秒
|
let today = dayjs().endOf('day').format('YYYY-MM-DD HH:mm:ss');
|
|
let params = {
|
column: 'createTime',
|
order: 'desc',
|
startTime_begin: daysAgo,
|
startTime_end: today,
|
pageNo: 1,
|
pageSize: 3
|
}
|
this.$api.queryHisFaultList(params).then((res) => {
|
this.faultList = res.result.records
|
}).catch(res => {
|
|
})
|
|
|
let chartParam = {
|
startTime_begin: daysAgo,
|
startTime_end: today,
|
}
|
this.statisData = {}
|
this.pieData = {}
|
this.wordData = {}
|
this.$api.queryHisFaultChartList(chartParam).then((res) => {
|
|
// 柱状图
|
const statis = {
|
series: [],
|
categories: []
|
};
|
//饼图
|
const pieData = {
|
series: [{
|
data: []
|
}]
|
};
|
//词云图
|
const wordData = {
|
series: []
|
};
|
this.$emit('handleData', res)
|
// 检查 res 是否为 null 或者不是一个数组
|
if (!Array.isArray(res) || res === null || res.length === 0) {
|
|
this.errorMessage1 = "暂无数据"+ dayjs().format('HH:mm:ss');
|
this.errorMessage2 = "暂无数据"+ dayjs().format('HH:mm:ss');
|
this.errorMessage3 = "暂无数据"+ dayjs().format('HH:mm:ss');
|
this.errorMessage4 = "暂无数据"+ dayjs().format('HH:mm:ss');
|
return;
|
}
|
|
|
console.error(res)
|
|
// 单次遍历 res,同时寻找最大 ecount 并构建 categories、data 和 pieData
|
const result = res.reduce((acc, item) => {
|
if (item.faultType === 1) {
|
acc.categories.push(item.faultName);
|
const value = item.ecount;
|
acc.data.push({
|
value,
|
color: undefined // 先不设定颜色
|
});
|
|
}
|
// 更新最大 ecount
|
if (item.ecount > acc.maxEcount) {
|
acc.maxEcount = item.ecount;
|
}
|
|
return acc;
|
}, {
|
maxEcount: 0,
|
categories: [],
|
data: []
|
});
|
|
// 第二次遍历 data 数组,为所有最大 ecount 设置颜色
|
result.data.forEach((item, index) => {
|
if (item.value === result.maxEcount) {
|
result.data[index].color = '#f04864';
|
}
|
});
|
|
// 将处理结果赋值给 statis
|
statis.series.push({
|
name: "故障",
|
data: result.data.map(item => 'color' in item ? item : item.value)
|
});
|
statis.categories = result.categories;
|
|
|
|
res.filter(item => item.faultType == 1).forEach(item => {
|
// 构建 pieData
|
pieData.series[0].data.push({
|
name: item.faultName,
|
value: item.ecount,
|
labelText: item.faultName + ":" + item.ecount + "次"
|
});
|
})
|
|
|
|
// 设置到组件属性
|
this.statisData = statis;
|
this.pieData = pieData;
|
if (this.statisData.series.length === 0) {
|
this.errorMessage1 = "暂无数据"+ dayjs().format('HH:mm:ss');
|
this.errorMessage4 = "暂无数据"+ dayjs().format('HH:mm:ss');
|
}
|
|
if (this.pieData.series[0].data.length === 0) {
|
this.errorMessage2 = "暂无数据"+ dayjs().format('HH:mm:ss');
|
}
|
|
|
const cdata = res.filter(item => item.faultType === 1).map(item => ({
|
faultName: item.faultName,
|
ecount: item.ecount
|
}));
|
console.error(cdata)
|
const wordCloudData = this.generateWordCloudData(cdata)
|
|
wordData.series = wordCloudData
|
this.wordData = wordData
|
console.error(this.wordData)
|
if (this.wordData.series.length === 0) {
|
this.errorMessage3 = "暂无数据"+ dayjs().format('HH:mm:ss');
|
}
|
|
|
}).catch(res => {
|
|
})
|
|
|
},
|
generateWordCloudData(data) {
|
// 定义字体大小范围
|
const minFontSize = 10;
|
const maxFontSize = 20;
|
|
// 如果数据为空或不是数组,则返回空数组
|
if (!Array.isArray(data) || data.length === 0) {
|
return [];
|
}
|
|
// 找到最大和最小的故障次数
|
let minCount = Infinity;
|
let maxCount = -Infinity;
|
|
data.forEach(item => {
|
if (item.ecount < minCount) minCount = item.ecount;
|
if (item.ecount > maxCount) maxCount = item.ecount;
|
});
|
|
// 如果所有故障次数都相同,则直接为每个条目设置相同的字体大小
|
if (minCount === maxCount) {
|
return data.map(item => ({
|
name: item.faultName,
|
textSize: maxFontSize
|
}));
|
}
|
|
// 计算每个条目的字体大小
|
const wordCloudData = data.map(item => {
|
const fontSize = ((maxFontSize - minFontSize) * (item.ecount - minCount)) / (maxCount -
|
minCount) + minFontSize;
|
return {
|
name: item.faultName,
|
textSize: Math.round(fontSize) // 可选:四舍五入到最接近的整数
|
};
|
});
|
return wordCloudData;
|
},
|
|
|
}
|
}
|
</script>
|
|
<style lang="scss" scoped>
|
@import "components/table/helang-table";
|
|
.app {}
|
|
.card-box {
|
margin: 20rpx;
|
padding: 20rpx;
|
box-sizing: border-box;
|
background-color: white;
|
border-radius: 20rpx;
|
font-family: Helvetica Neue, Helvetica, sans-serif;
|
|
}
|
|
.text-ellipsis {
|
white-space: nowrap;
|
/* 防止文本换行 */
|
overflow: hidden;
|
/* 超出部分隐藏 */
|
text-overflow: ellipsis;
|
/* 超出部分用省略号表示 */
|
max-width: 100%;
|
/* 设置最大宽度 */
|
|
}
|
|
|
.top {
|
margin: 0 20rpx;
|
border-radius: 0;
|
border-top-left-radius: 20rpx;
|
border-top-right-radius: 20rpx;
|
border-bot-left-radius: 0;
|
border-bot-right-radius: 0;
|
|
}
|
|
.center {
|
margin: 0 20rpx;
|
border-radius: 0;
|
|
}
|
|
.bot {
|
margin: 0 20rpx 20rpx 20rpx;
|
border-top-left-radius: 0;
|
border-top-right-radius: 0;
|
border-bot-left-radius: 20rpx;
|
border-bot-right-radius: 20rpx;
|
}
|
|
|
.title-box {
|
display: flex;
|
flex-direction: row;
|
align-items: center;
|
|
.left {
|
display: flex;
|
align-items: center;
|
|
.title {
|
margin: 0 10rpx;
|
font-weight: bold;
|
}
|
}
|
|
.right {
|
display: flex;
|
align-items: center;
|
|
.title {
|
margin: 0 10rpx;
|
font-weight: bold;
|
}
|
}
|
}
|
|
.info-box {
|
margin-top: 20rpx;
|
display: flex;
|
flex-direction: row;
|
align-items: center;
|
|
.left {
|
display: flex;
|
align-items: center;
|
|
.title {
|
margin: 0 10rpx;
|
}
|
}
|
|
.right {
|
display: flex;
|
align-items: center;
|
|
.title {
|
margin: 0 10rpx;
|
}
|
}
|
}
|
|
|
.chartsMain {
|
width: 100%;
|
height: 320rpx;
|
padding-top: 15rpx;
|
background: #fff;
|
margin-bottom: 24rpx;
|
border-top: 2rpx solid #f2f2f2;
|
|
.charts {
|
width: 50%;
|
height: 450rpx;
|
box-sizing: border-box;
|
}
|
}
|
|
.tab-box {
|
display: flex;
|
justify-content: center;
|
/* 强制水平居中 */
|
}
|
|
.swiper {
|
height: 2116rpx;
|
}
|
|
.swiper-item-view {
|
height: 2116rpx;
|
|
|
}
|
|
|
|
|
|
|
|
.picBox {
|
margin: 0 20rpx;
|
background-color: white;
|
|
image {
|
border-radius: 8rpx;
|
width: 100%;
|
|
}
|
}
|
|
.borderTop {
|
border-top: 2rpx solid #f2f2f2;
|
padding-top: 20rpx;
|
}
|
|
// 弹出层背景遮罩start
|
.dropdown-mask {
|
background: rgba(0, 0, 0, 0.5);
|
}
|
|
.lock-page {
|
height: 100vh;
|
width: 100vw;
|
position: fixed;
|
top: 0;
|
left: 0;
|
right: 0;
|
bottom: 0;
|
z-index: 998;
|
}
|
|
// 弹出层背景遮罩end
|
</style>
|