Files
emsapp/pages/work/dtdc/index.vue
2025-08-17 01:13:04 +08:00

502 lines
11 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="search-icon" @click="openSearch">
<uni-icons type="search" size="40" color="#fff"></uni-icons>
</view>
<view class="list-container">
<view class="no-data" v-if="list.length === 0">暂无数据</view>
<uni-list v-else>
<uni-list-item v-for="(item,index) in list" :key="index+'dtdc'">
<template v-slot:header>
<view class="list-header">
单体编号:{{item.deviceId}}
<button type="primary" size="mini" class="charts" @click="toDetail(item)">图表</button>
</view>
</template>
<template v-slot:body>
<view class="list-body">
<uni-row>
<uni-col :span="8">
<view>簇号</view>
</uni-col>
<uni-col :span="14">
<view class="right">{{item.clusterDeviceId}}</view>
</uni-col>
</uni-row>
<uni-row>
<uni-col :span="8">
<view>电压V</view>
</uni-col>
<uni-col :span="14">
<view class="right color" @click="toDetail(item,'voltage')">{{item.voltage}}
</view>
</uni-col>
</uni-row>
<uni-row>
<uni-col :span="8">
<view>温度</view>
</uni-col>
<uni-col :span="14">
<view class="right color" @click="toDetail(item,'temperature')">
{{item.temperature}}
</view>
</uni-col>
</uni-row>
<uni-row>
<uni-col :span="8">
<view>SOC%</view>
</uni-col>
<uni-col :span="14">
<view class="right color" @click="toDetail(item,'soc')">{{item.soc}}</view>
</uni-col>
</uni-row>
<uni-row>
<uni-col :span="8">
<view>SOH%</view>
</uni-col>
<uni-col :span="14">
<view class="right color" @click="toDetail(item,'soh')">{{item.soh}}</view>
</uni-col>
</uni-row>
</view>
</template>
</uni-list-item>
</uni-list>
</view>
<uni-popup ref="popup" type="center" :animation="false" :mask-click="false" :is-mask-click="false"
@maskClick="maskClick">
<view class="chart-popup" v-if="showChart">
<uni-datetime-picker v-model="range" type="daterange" :end="end" rangeSeparator="至" @change="changeTime"
style="margin-bottom: 10px;" />
<view class="chart-container">
<qiun-data-charts type="line" :reload="showChart" :optsWatch='false' :opts="options"
:chartData="chartsData" :ontouch="true" :inScrollView="true" :pageScrollTop="pageScrollTop" />
</view>
</view>
</uni-popup>
<uni-popup ref="searchPopup" type="center">
<view class="uni-pa-5 search-container">
<uni-forms ref="form">
<uni-forms-item label="电池堆">
<uni-data-select :clear="false" v-model="search.stackId" :localdata="stackOptions"
@change="changeStackId"></uni-data-select>
</uni-forms-item>
<uni-forms-item label="电池簇">
<uni-data-select :clear="false" v-model="search.clusterId"
:localdata="clusterOptions"></uni-data-select>
</uni-forms-item>
<uni-forms-item label="编号">
<uni-easyinput type="text" v-model="search.batteryId" placeholder="请输入编号" />
</uni-forms-item>
</uni-forms>
<view class="button-group" style="text-align: center;">
<button type="default" size="mini" @click="onReset">重置</button>
<button type="primary" size="mini" @click="onSearch" style="margin-left: 20px;">搜索</button>
</view>
</view>
</uni-popup>
</view>
</template>
<script>
// import Chart from './Chart.vue'
import {
getStackNameList,
getClusterNameList,
getClusterDataInfoList,
getSingleBatteryData
} from '@/api/ems/site.js'
import {
mapState
} from 'vuex'
export default {
components: {
// Chart
},
computed: {
...mapState({
workStatusOptions: (state) =>
state.ems.workStatusOptions,
communicationStatusOptions: (state) =>
state.ems.communicationStatusOptions,
})
},
data() {
return {
pageNum: 1,
pageSize: 20,
total: 0,
stackOptions: [],
clusterOptions: [],
search: {
stackId: '',
clusterId: '',
batteryId: ''
},
list: [],
siteId: '',
pageScrollTop: 0,
// ucharts数据
showChart: false,
chartSearchData: {
},
options: {
duration: 0,
animation: false,
dataLabel: false,
enableScroll: true,
xAxis: {
scrollShow: true,
itemCount: 3,
disableGrid: true
},
},
range: [],
end: Date.now(),
loading: false,
chartsData: {},
// ucharts数据结束
}
},
onPageScroll(e) {
this.pageScrollTop = e.scrollTop
},
onReachBottom() {
if (this.list.length >= this.total) {
return console.log('数据已经加载完成')
}
this.pageNum += 1 //每次搜索从1开始搜索
this.getTableData()
},
methods: {
//ucharts方法
maskClick() {
this.showChart = false
this.$refs.popup.close()
},
chartOpen({
siteId,
clusterDeviceId,
deviceId
}, dataType) {
this.loading = false
this.range = []
this.chartSearchData = {
clusterDeviceId,
deviceId,
dataType
}
this.$refs.popup.open()
setTimeout(() => {
this.showChart = true
this.getChartData()
}, 100)
},
changeTime(val) {
this.range = val || []
this.getChartData()
},
getChartData() {
if (this.loading) return
this.loading = true;
const {
siteId,
chartSearchData: {
deviceId,
clusterDeviceId
},
range: [startDate = '', endDate = '']
} = this;
this.chartsData = {}
return getSingleBatteryData({
siteId,
deviceId,
clusterDeviceId,
startDate,
endDate
}).then(response => {
this.handledata(response?.data || [])
}).finally(() => {
this.loading = false;
})
},
handledata(data) {
let obj = {
voltage: '电压',
temperature: '温度',
soc: 'SOC',
soh: 'SOH',
},
categories = [],
dataTypeList = [],
{
dataType
} = this.chartSearchData
if (dataType) {
dataTypeList = [{
attr: dataType,
title: obj[dataType],
data: []
}]
} else {
dataTypeList = Object.entries(obj).map(([key, value]) => {
return {
attr: key,
title: value,
data: []
}
})
}
data.forEach(item => {
categories.push(item.dataTimestamp)
dataTypeList.forEach(i => {
i.data.push(item[i.attr] || undefined)
})
})
const series = dataTypeList.map(item => {
return {
"name": item.title,
"data": item.data
}
})
this.chartsData = JSON.parse(JSON.stringify({
categories,
series
}))
console.log('this.chartsData', this.chartsData)
},
//ucharts方法结束
openSearch() {
this.$refs.searchPopup.open()
},
closeSearch() {
this.$refs.searchPopup.close()
},
toDetail(item, dataType) {
const {
clusterDeviceId,
deviceId
} = item, {
siteId
} = this
// this.$refs.chart.open({
this.chartOpen({
siteId,
clusterDeviceId,
deviceId
}, dataType)
},
// 搜索
onSearch() {
this.pageNum = 1 //每次搜索从1开始搜索
this.getTableData(true)
this.closeSearch()
},
// 重置
// 清空搜索栏选中数据
// 清空电池簇列表,保留电池堆列表
onReset() {
this.search = {
stackId: '',
clusterId: '',
batteryId: ''
}
this.clusterOptions = []
this.pageNum = 1
this.getTableData(true)
this.closeSearch()
},
changeStackId(val) {
if (val) {
console.log('选择了电池堆,需要获取对应的电池簇', val, this.search.stackId)
this.search.clusterId = ''
this.getClusterList()
}
},
getStackList() {
getStackNameList({
siteId: this.siteId
}).then(response => {
this.stackOptions = JSON.parse(JSON.stringify(response?.data || [])).map(item => {
return {
text: item.deviceName,
value: item.id
}
})
})
},
getClusterList() {
getClusterNameList({
stackDeviceId: this.search.stackId,
siteId: this.siteId
}).then(response => {
this.clusterOptions = JSON.parse(JSON.stringify(response?.data || [])).map(item => {
return {
text: item.deviceName,
value: item.id
}
})
}).finally(() => {})
},
//表格数据
getTableData(reset = false) {
if (!reset && this.list.length === this.total) return
uni.showLoading()
if (reset) {
this.list = []
this.total = 0
}
const {
stackId: stackDeviceId,
clusterId: clusterDeviceId,
batteryId
} = this.search
const {
siteId,
pageNum,
pageSize
} = this
getClusterDataInfoList({
stackDeviceId,
clusterDeviceId,
batteryId,
siteId,
pageNum,
pageSize
}).then(response => {
this.list = this.list.concat(response?.rows?.[0]?.batteryList || []);
this.total = response?.total || 0
}).finally(() => {
uni.hideLoading()
})
},
},
mounted() {
// uni.showLoading()
this.siteId = this.$route.query.siteId || ''
this.getStackList()
this.getTableData(true)
}
}
</script>
<style lang="scss" scoped>
.container {
position: relative;
// position: fixed;
// width: 100%;
// height: 100%;
// overflow-y: auto;
.search-icon {
position: fixed;
bottom: 20px;
right: 20px;
z-index: 1;
height: 50px;
width: 50px;
background-color: #007aff;
border-radius: 100%;
line-height: 50px;
text-align: center;
}
.search-container {
background: #ffffff;
width: 360px;
padding: 15px 20px;
}
.list-container {
// z-index: 10;
padding-top: 20px;
padding-bottom: 50px;
background: #ffffff;
::v-deep {
.uni-list-item {
padding: 12px 15px;
}
.uni-list-item__container {
padding: 0;
display: block;
box-shadow: 0 1px 8px 1px rgba($color: #a5a5a5, $alpha: 0.2);
}
.uni-list--border-top,
.uni-list--border-bottom,
.uni-list--border::after {
background-color: transparent;
}
}
.list-header {
background-color: #05AEA3;
color: #fff;
padding: 10px 15px;
border-radius: 5px 5px 0 0;
position: relative;
.charts {
position: absolute;
top: 50%;
right: 15px;
transform: translateY(-50%);
// background-color: #ff7300;
}
}
.list-body {
padding: 10px 15px;
border: 1px solid #eee;
border-top: none;
border-radius: 0 0 5px 5px;
font-size: 14px;
color: #666;
.right {
color: #000;
}
.color {
color: #007aff;
}
.uni-row {
margin-bottom: 10px;
&:last-child {
margin-bottom: 0;
}
}
}
}
.chart-popup {
width: 360px;
background-color: #fff;
padding: 10px 15px;
.chart-container {
width: 100%;
height: 250px;
margin-top: 20px;
}
::v-deep {
uni-canvas {
height: 250px;
width: 100%;
}
}
}
}
</style>