<script setup name="battCell">
|
import { ref, reactive, onMounted, computed, nextTick } from "vue";
|
import useElement from "@/hooks/useElement.js";
|
|
import barChart from '@/components/echarts/bar1.vue';
|
import lineChart from '@/components/echarts/line3.vue';
|
import * as echarts from 'echarts';
|
import moment from 'moment';
|
|
import {
|
getSingleStatistic,
|
battMonExport,
|
} from "@/api/statistic.js";
|
|
import {
|
getBatteryBrand,
|
getMonCapByUid,
|
getMonVol,
|
} from "@/api/station";
|
|
const { $loading, $message, $confirm } = useElement();
|
const barLabels = ['优秀', '劣化', '损坏'];
|
|
const chart0 = ref(null);
|
const chart1 = ref(null);
|
const chart2 = ref(null);
|
const allGraph = ref(null);
|
|
let allGraphInstance = null;
|
|
const goodlistNum = ref(0);
|
const badlistNum = ref(0);
|
const damagelistNum = ref(0);
|
const goodlist = ref([]);
|
const badlist = ref([]);
|
const damagelist = ref([]);
|
|
|
const chartData = reactive({
|
chart0: {
|
labels: [],
|
volDatas: [],
|
resDatas: [],
|
},
|
chart1: {
|
labels: [],
|
volDatas: [],
|
resDatas: [],
|
},
|
chart2: {
|
labels: [],
|
volDatas: [],
|
resDatas: [],
|
},
|
});
|
|
const startDate0 = '2025-01-01 00:00:00';
|
|
const startDate = ref(moment().subtract(30, 'day').format('YYYY-MM-DD'));
|
const endDate = ref(moment().format('YYYY-MM-DD'));
|
const moncapstd = ref('');
|
const monvolstd = ref('');
|
const product = ref('');
|
|
|
const startDisabledDate = (time) => endDate.value ? moment(endDate.value).isBefore(time) || moment().isBefore(time) : moment().isBefore(time);
|
|
const endDisabledDate = (time) => startDate.value ? moment(time).isBefore(startDate.value) || moment().isBefore(time) : moment().isBefore(time);
|
|
function formatData(list, idx) {
|
list.forEach(item => {
|
chartData[`chart${idx}`].labels.push(`${item.battgroupName}-#${item.monNum}`);
|
chartData[`chart${idx}`].volDatas.push(item.monVol);
|
chartData[`chart${idx}`].resDatas.push(item.monRes);
|
});
|
}
|
|
const currType = ref(0);
|
const productList = ref([]);
|
const monCapList = ref([]);
|
const monVolList = ref([]);
|
const lastParams = ref({});
|
|
// 获取标称容量
|
function getMonCapList() {
|
getMonCapByUid().then((res) => {
|
let { code, data, data2 } = res;
|
let list = [];
|
if (code && data) {
|
list = data2;
|
}
|
monCapList.value = list;
|
});
|
}
|
|
function getMonVolList() {
|
getMonVol().then((res) => {
|
let { code, data, data2 } = res;
|
let list = [];
|
if (code && data) {
|
list = data2;
|
}
|
monVolList.value = list;
|
});
|
}
|
|
function getList() {
|
let loading = $loading();
|
let params = {
|
endTime: endDate.value ? endDate.value + ' 23:59:59' : moment().format('YYYY-MM-DD') + ' 23:59:59',
|
startTime: startDate.value ? startDate.value + ' 00:00:00' : startDate0,
|
product: product.value || undefined,
|
moncapstd: moncapstd.value || undefined,
|
monvolstd: monvolstd.value || undefined,
|
};
|
|
lastParams.value = params;
|
|
getSingleStatistic(params)
|
.then((res) => {
|
let { code, data, data2 } = res;
|
let gList = [];
|
let bList = [];
|
let dList = [];
|
|
let gNum = 0;
|
let bNum = 0;
|
let dNum = 0;
|
|
loading.close();
|
if (code && data) {
|
gList = data2.goodlist;
|
bList = data2.badlist;
|
dList = data2.damagelist;
|
gNum = data2.goodlistNum;
|
bNum = data2.badlistNum;
|
dNum = data2.damagelistNum;
|
}
|
goodlistNum.value = gNum;
|
badlistNum.value = bNum;
|
damagelistNum.value = dNum;
|
goodlist.value = gList;
|
badlist.value = bList;
|
damagelist.value = dList;
|
|
formatData(gList, 0);
|
formatData(bList, 1);
|
formatData(dList, 2);
|
|
updateBarChart();
|
updateLineChart();
|
})
|
.catch((err) => {
|
console.log(err);
|
loading.close();
|
});
|
}
|
|
function updateBarChart() {
|
if (chart0.value) {
|
chart0.value.updateChart(barLabels, [goodlistNum.value, badlistNum.value, damagelistNum.value]);
|
}
|
}
|
|
function updateLineChart() {
|
let idx = currType.value;
|
if (chart1.value) {
|
chart1.value.updateChart(chartData[`chart${idx}`].labels, chartData[`chart${idx}`].volDatas);
|
}
|
if (chart2.value) {
|
chart2.value.updateChart(chartData[`chart${idx}`].labels, chartData[`chart${idx}`].resDatas);
|
}
|
}
|
|
function getProductList() {
|
getBatteryBrand().then((res) => {
|
let { code, data, data2 } = res;
|
let list = [];
|
if (code && data) {
|
list = data2;
|
}
|
productList.value = list;
|
});
|
}
|
|
function createGraphByOpt (xLabels, datas) {
|
xLabels = xLabels || [];
|
datas = datas || [];
|
allGraphInstance.clear();
|
let lineStyle = {
|
color: "#000",
|
};
|
let opt = {
|
animation: false,
|
grid: {
|
left: '3%',
|
right: '4%',
|
bottom: '3%',
|
top: 30,
|
containLabel: true
|
},
|
xAxis: [{
|
type: 'category',
|
// boundaryGap: false,
|
axisLine: {
|
lineStyle
|
},
|
data: xLabels
|
}],
|
yAxis: [{
|
type: 'value',
|
axisTick: {
|
show: true,
|
},
|
axisLine: {
|
show: true,
|
lineStyle
|
},
|
splitLine: {
|
show: false
|
}
|
}],
|
series: [{
|
type: 'line',
|
smooth: true,
|
symbolSize: 0,
|
lineStyle,
|
data: datas
|
}]
|
};
|
allGraphInstance.setOption(opt);
|
|
return allGraphInstance.getDataURL({ pixelRatio: 1, backgroundColor: "#fff" });
|
}
|
|
|
async function exportFile () {
|
let img0 = chart0.value.getDataURL();
|
|
let params = {
|
...lastParams.value,
|
topPic: img0,
|
goodVolPic: createGraphByOpt(chartData.chart0.labels, chartData.chart0.volDatas),
|
goodResPic: createGraphByOpt(chartData.chart0.labels, chartData.chart0.resDatas),
|
badVolPic: createGraphByOpt(chartData.chart1.labels, chartData.chart1.volDatas),
|
badResPic: createGraphByOpt(chartData.chart1.labels, chartData.chart1.resDatas),
|
damageVolPic: createGraphByOpt(chartData.chart2.labels, chartData.chart2.volDatas),
|
damageResPic: createGraphByOpt(chartData.chart2.labels, chartData.chart2.resDatas),
|
};
|
|
// console.log('params', 'export', params, '=============');
|
let loading = $loading();
|
try {
|
let res = await battMonExport(params);
|
// console.log('res', res, '=============');
|
loading.close();
|
const nameList = res.headers["content-disposition"];
|
const fileName = nameList.split("=")[1];
|
let blob = res.data;
|
let url = window.URL.createObjectURL(blob);
|
let a = document.createElement("a");
|
a.href = url;
|
a.download = decodeURIComponent(fileName);
|
a.click();
|
window.URL.revokeObjectURL(url);
|
} catch (error) {
|
loading.close();
|
console.log('error', error, '=============');
|
$message.error("导出失败");
|
}
|
}
|
|
onMounted(() => {
|
getProductList();
|
getMonCapList();
|
getMonVolList();
|
|
getList();
|
// 绑定事件
|
if (chart0.value) {
|
chart0.value.getChart().on('click', function (params) {
|
// console.log('params', params, '=============');
|
if (params.componentType == 'series') {
|
currType.value = params.dataIndex;
|
updateLineChart();
|
}
|
});
|
}
|
|
if (allGraph.value) {
|
allGraphInstance = echarts.init(allGraph.value, 'transparent');
|
}
|
});
|
</script>
|
|
<template>
|
<div class="page-wrapper">
|
<!-- <div class="page-header">
|
</div> -->
|
<div class="page-content">
|
<yc-card is-full>
|
<div class="page-content-wrapper">
|
<div class="page-content-tools page-filter">
|
<div class="grid-container" :style="{'--counter': 8}">
|
<div class="grid-item">
|
<div class="label">品牌</div>
|
<div class="value">
|
<el-select
|
v-model="product"
|
filterable
|
clearable
|
placeholder="请选择"
|
style="width: 180px"
|
>
|
<el-option
|
v-for="(item, idx) in productList"
|
:key="'list10_' + idx"
|
:label="item"
|
:value="item"
|
/>
|
</el-select>
|
</div>
|
</div>
|
<div class="grid-item">
|
<div class="label">投运时间</div>
|
<div class="value" style="grid-column: span 5;">
|
<el-date-picker
|
v-model="startDate"
|
type="date"
|
size="small"
|
placeholder="选择日期"
|
format="YYYY-MM-DD"
|
value-format="YYYY-MM-DD"
|
:disabled-date="startDisabledDate"
|
/>
|
-
|
<el-date-picker
|
v-model="endDate"
|
size="small"
|
type="date"
|
placeholder="选择日期"
|
format="YYYY-MM-DD"
|
value-format="YYYY-MM-DD"
|
:disabled-date="endDisabledDate"
|
/>
|
</div>
|
</div>
|
<div class="grid-item">
|
<div class="label">标称容量</div>
|
<div class="value">
|
<el-select
|
v-model="moncapstd"
|
filterable
|
clearable
|
placeholder="请选择"
|
style="width: 180px"
|
>
|
<el-option
|
v-for="(item, idx) in monCapList"
|
:key="'list11_' + idx"
|
:label="item"
|
:value="item"
|
/>
|
</el-select>
|
</div>
|
</div>
|
<div class="grid-item">
|
<div class="label">电压等级</div>
|
<div class="value">
|
<el-select
|
v-model="monvolstd"
|
filterable
|
clearable
|
placeholder="请选择"
|
style="width: 180px"
|
>
|
<el-option
|
v-for="(item, idx) in monVolList"
|
:key="'list9_' + idx"
|
:label="item"
|
:value="item"
|
/>
|
</el-select>
|
</div>
|
<div class="btn-grp">
|
<el-button type="primary" size="small" @click="getList">查询</el-button>
|
<el-button type="warning" size="small" @click="exportFile">导出</el-button>
|
</div>
|
</div>
|
</div>
|
</div>
|
<div class="page-content-table">
|
<div class="pos-rel">
|
<div class="pos-abs">
|
<div class="left">
|
<card title="单体优秀/劣化/损坏统计图">
|
<bar-chart ref="chart0"></bar-chart>
|
</card>
|
</div>
|
<div class="right">
|
<div class="top">
|
<card title="浮充电压">
|
<line-chart ref="chart1"></line-chart>
|
</card>
|
</div>
|
<div class="bottom">
|
<card title="单体内阻">
|
<line-chart ref="chart2"></line-chart>
|
</card>
|
</div>
|
</div>
|
</div>
|
</div>
|
</div>
|
</div>
|
</yc-card>
|
</div>
|
<div class="page-footer"></div>
|
<div class="allGraph">
|
<div class="chart-contain">
|
<div class="chart" ref="allGraph"></div>
|
</div>
|
</div>
|
</div>
|
</template>
|
|
<style scoped lang="less">
|
.page-wrapper {
|
display: flex;
|
flex-direction: row;
|
// padding: 8px;
|
height: 100%;
|
|
.page-content {
|
flex: 1;
|
padding-bottom: 8px;
|
}
|
}
|
|
.page-content-wrapper {
|
display: flex;
|
flex-direction: column;
|
height: 100%;
|
|
.page-content-tools {
|
padding-bottom: 8px;
|
|
.flex-row {
|
display: flex;
|
align-items: center;
|
:deep(.el-checkbox) {
|
color: #fff;
|
}
|
.group {
|
margin-left: 30px;
|
}
|
}
|
}
|
|
.page-content-table {
|
// border-top: 1px solid var(--border-light-color);
|
box-sizing: border-box;
|
flex: 1;
|
margin-left: 26px;
|
margin-right: 26px;
|
}
|
|
.page-content-page {
|
padding: 8px 8px 0 8px;
|
text-align: center;
|
|
.el-page-container {
|
display: inline-block;
|
padding: 0 16px;
|
}
|
|
.page-tool {
|
display: inline-block;
|
}
|
}
|
}
|
|
.hdw-card-container {
|
width: 240px;
|
padding-right: 8px;
|
height: 100%;
|
}
|
|
.pos-rel {
|
position: relative;
|
width: 100%;
|
height: 100%;
|
|
.pos-abs {
|
position: absolute;
|
top: 0;
|
bottom: 0;
|
left: 0;
|
right: 0;
|
width: 100%;
|
height: 100%;
|
display: flex;
|
|
.left {
|
width: 400px;
|
margin-right: 10px;
|
}
|
.right {
|
flex: 1;
|
display: flex;
|
flex-direction: column;
|
.top {
|
flex: 1;
|
}
|
.bottom {
|
margin-top: 10px;
|
flex: 1;
|
}
|
}
|
}
|
}
|
|
.allGraph {
|
position: absolute;
|
top: -1000px;
|
left: 0;
|
width: 600px;
|
height: 400px;
|
.chart-contain {
|
height: 100%;
|
width: 100%;
|
.chart {
|
height: 100%;
|
width: 100%;
|
}
|
}
|
}
|
|
.tools-filter {
|
display: inline-block;
|
font-size: 14px;
|
|
.tools-filter-item {
|
display: inline-block;
|
margin-right: 8px;
|
|
.filter-label {
|
display: inline-block;
|
}
|
|
.filter-content {
|
display: inline-block;
|
}
|
}
|
}
|
</style>
|