<template>
|
<flex-layout :loading="loading" no-bg>
|
<div slot="header">
|
<div class="table-layout filter-box-table">
|
<div class="table-row">
|
<div class="table-cell text-right">文件名称:</div>
|
<div class="table-cell" style="width: 320px">
|
<el-input v-model="params.fileName" size="small" disabled></el-input>
|
</div>
|
<div class="table-cell text-right">电池类型(V):</div>
|
<div class="table-cell">
|
<el-input v-model="params.batteryType" size="small" disabled></el-input>
|
</div>
|
<div class="table-cell text-right">标称容量(AH):</div>
|
<div class="table-cell">
|
<el-input v-model="params.nominalCap" size="small" disabled></el-input>
|
</div>
|
<div class="table-cell text-right">标称内阻(mΩ):</div>
|
<div class="table-cell">
|
<el-input v-model="params.nominalRes" size="small" disabled></el-input>
|
</div>
|
<div class="table-cell text-right">实际内阻(mΩ):</div>
|
<div class="table-cell">
|
<el-input v-model="params.initRes" size="small" disabled></el-input>
|
</div>
|
<div class="table-cell text-right">放电小时率(C):</div>
|
<div class="table-cell">
|
<el-input v-model="params.hourRate" size="small" disabled></el-input>
|
</div>
|
<div class="table-cell" style="text-align: center">
|
<el-button type="primary" size="mini" @click="battInfoDialog=true">导入数据</el-button>
|
<el-upload
|
class="upload-demo"
|
ref="upload"
|
:action="action"
|
multiple
|
:limit="1"
|
:show-file-list="false"
|
:file-list="fileList"
|
:before-upload="beforeUpload"
|
:on-progress="onProgress"
|
:on-success="onSuccess"
|
:on-error="onError">
|
<el-button type="warning" size="mini">导入标准曲线</el-button>
|
</el-upload>
|
</div>
|
</div>
|
</div>
|
</div>
|
<div class="page-content">
|
<div class="page-content-container top">
|
<div class="top-container left">
|
<flex-box title="总电压" size="mini">
|
<div class="totalVol-tools" slot="tools">
|
<span>放电测试时长:</span>
|
<el-select size="mini" v-model="timeValue" filterable @change="searchStanderLine">
|
<el-option
|
v-for="(item, key) in timeList"
|
:key="'key'+key"
|
:value="item.value"
|
:label="item.label"></el-option>
|
</el-select>
|
</div>
|
<line-chart ref="totalVol" unit="V"></line-chart>
|
</flex-box>
|
</div>
|
<div class="top-container right">
|
<flex-box title="总电流" size="mini">
|
<line-chart ref="totalCurr" unit="A"></line-chart>
|
</flex-box>
|
</div>
|
</div>
|
<div class="page-content-container bottom">
|
<div class="top-container left">
|
<flex-box title="数据源" size="mini">
|
<el-table
|
stripe
|
size="small"
|
:data="dataTbl"
|
height="100%">
|
<el-table-column
|
prop="time"
|
align="center"
|
label="测试时间">
|
</el-table-column>
|
<el-table-column
|
prop="groupVol"
|
align="center"
|
label="总电压">
|
</el-table-column>
|
<el-table-column
|
prop="groupCurr"
|
align="center"
|
label="总电流">
|
</el-table-column>
|
</el-table>
|
</flex-box>
|
</div>
|
<div class="top-container right">
|
<flex-box title="三维度综合权重计算法" size="mini">
|
<table class="table-container">
|
<tr>
|
<td rowspan="2">电池标称值</td>
|
<td colspan="2">电池类型(V)</td>
|
<td colspan="2">标称容量(AH)</td>
|
<td>标称内阻r(mΩ)</td>
|
</tr>
|
<tr>
|
<td colspan="2">
|
<change-text label="电池类型" unit="V" v-model="params.batteryType"></change-text>
|
</td>
|
<td colspan="2">
|
<change-text label="标称容量" unit="AH" v-model="params.nominalCap"></change-text>
|
</td>
|
<td>
|
<change-text label="标称内阻" unit="mΩ" v-model="params.nominalRes"></change-text>
|
</td>
|
</tr>
|
<tr>
|
<td colspan="6">性能评价-计算容量与标称容量之比</td>
|
</tr>
|
<tr>
|
<td>维度</td>
|
<td colspan="3">驼峰锅底</td>
|
<td>预估容量(AH)</td>
|
<td>实际内阻</td>
|
</tr>
|
<tr>
|
<td>维度值</td>
|
<td>正常</td>
|
<td>不正常</td>
|
<td>可能</td>
|
<td>
|
<change-text no-change label="预估容量" unit="AH" v-model="params.realCap"></change-text>
|
</td>
|
<td>
|
<change-text label="实际内阻" unit="mΩ" v-model="params.initRes"></change-text>
|
</td>
|
</tr>
|
<tr>
|
<td>容量百分比</td>
|
<td>
|
<change-text label="驼峰锅底-正常权重" unit="%" show-unit v-model="humpPotBottom.normal"></change-text>
|
</td>
|
<td>
|
<change-text label="驼峰锅底-不正常权重" unit="%" show-unit v-model="humpPotBottom.abnormal"></change-text>
|
</td>
|
<td>
|
<change-text label="驼峰锅底-不正常权重" unit="%" show-unit v-model="humpPotBottom.mayBeAbnormal"></change-text>
|
</td>
|
<td>
|
<change-text no-change label="容量百分比" unit="%" show-unit :value="capPercent"></change-text>
|
</td>
|
<td>
|
<change-text label="内阻百分比" unit="%" show-unit :value="resPercent"></change-text>
|
</td>
|
</tr>
|
<tr>
|
<td>
|
维度权重
|
</td>
|
<td colspan="3">
|
<change-text label="维度权重-驼峰锅底" unit="%" show-unit v-model="dimensionWeight.humpPotBottom"></change-text>
|
</td>
|
<td>
|
<change-text label="维度权重-容量" unit="%" show-unit v-model="dimensionWeight.cap"></change-text>
|
</td>
|
<td>
|
<change-text label="维度权重-内阻" unit="%" show-unit v-model="dimensionWeight.res"></change-text>
|
</td>
|
</tr>
|
<tr>
|
<td rowspan="2">
|
结果
|
</td>
|
<td colspan="5">
|
<change-text no-change label="最终结果" unit="%" show-unit :value="resultInfo.value"></change-text>
|
</td>
|
</tr>
|
<tr>
|
<td colspan="5">
|
<change-text no-change label="最终结果" show-unit :value="resultInfo.label"></change-text>
|
</td>
|
</tr>
|
<tr>
|
<td>
|
系统提示
|
</td>
|
<td colspan="5" class="error-message">
|
{{ errorMessage }}
|
</td>
|
</tr>
|
</table>
|
</flex-box>
|
</div>
|
</div>
|
</div>
|
<!-- 电池信息 -->
|
<el-dialog
|
title="电池参数设置"
|
width="auto"
|
:visible.sync="battInfoDialog"
|
:close-on-click-modal="false"
|
top="0"
|
class="dialog-center"
|
:modal-append-to-body="false">
|
<batt-info
|
v-if="battInfoDialog"
|
:visible.sync="battInfoDialog" @success="setBattData"></batt-info>
|
</el-dialog>
|
</flex-layout>
|
</template>
|
|
<script>
|
import FlexBox from "@/components/FlexBox";
|
import getWebUrl from "@/assets/js/tools/getWebUrl";
|
import LineChart from "@/components/myCharts/LineChart";
|
import {formatSeconds} from "@/assets/js/tools";
|
import getSpecialPointIndex from "@/assets/js/tools/getSpecialPointIndex";
|
import battInfo from "@/views/dataTest/components/meterData/battInfo";
|
import getQgth from "@/assets/js/tools/getQgth";
|
import {searchStandardLine} from "@/views/dataTest/js/meterData";
|
import formatTime from "@/assets/js/tools/formatTime"
|
import ChangeText from "@/components/ChangeText";
|
import getRealCapFromStandardLine from "@/assets/js/tools/getRealCapFromStandardLine";
|
import getFirstTestData from "@/assets/js/tools/getFirstTestData";
|
export default {
|
name: "dischargeMeterData",
|
components: {ChangeText, FlexBox, LineChart, battInfo},
|
totalCurrOpt() {
|
return {
|
grid: {
|
top: '12px',
|
left: '1%',
|
right: '32px',
|
bottom: '2%',
|
containLabel: true
|
},
|
series: [
|
{
|
name: "总电流",
|
data: []
|
}
|
]
|
};
|
},
|
totalVolOpt() {
|
return {
|
title: {
|
show: true,
|
text: "",
|
x: 'center',
|
textStyle: {
|
fontSize: 14,
|
}
|
},
|
grid: {
|
left: '1%',
|
right: '32px',
|
bottom: '2%',
|
containLabel: true
|
},
|
series: [
|
{
|
name: "总电压",
|
data: [],
|
markLine: {}
|
}
|
]
|
}
|
},
|
standardData: [],
|
dischargeData: [],
|
formatRs: {
|
totalVol: [],
|
totalCurr: [],
|
dataTbl: [],
|
},
|
specialPoint() {
|
return {
|
code: 0, // 标识是否找到驼峰锅底
|
min: -Infinity, // 锅底所在的点
|
minVal: 0,
|
max: Infinity, // 驼峰所在的点
|
maxVal: 0,
|
}
|
},
|
data() {
|
return {
|
loading: false,
|
battInfoDialog: false,
|
params: {
|
batteryType: "", // 电池类型
|
nominalCap: "", // 标称容量
|
nominalRes: "", // 标称内阻
|
initRes: "", // 实际内阻
|
hourRate: "", // 放电小时率
|
monNum: 1, // 单体个数
|
realCap: "", // 实际容量
|
fileName: "",
|
},
|
humpPotBottom: {
|
normal: 90,
|
abnormal: 30,
|
mayBeAbnormal: 60
|
},
|
dimensionWeight: {
|
humpPotBottom: 20,
|
cap: 70,
|
res: 10
|
},
|
rules: {},
|
action: getWebUrl()+"standardFeatureCurve/excelImport",
|
fileList: [],
|
isHasDischargeData: 0,
|
isHasSpecial: 0,
|
isHasStandardLine: 0,
|
qgth: {},
|
dataTbl: [],
|
timeValue: "",
|
timeList: []
|
}
|
},
|
watch: {
|
"params.batteryType"() {
|
this.searchStanderLine();
|
},
|
"params.nominalCap"() {
|
this.searchStanderLine();
|
}
|
},
|
methods: {
|
beforeUpload() {
|
this.loading = true;
|
},
|
onProgress() {
|
this.loading = true;
|
},
|
onSuccess(res) {
|
this.loading = false;
|
this.$refs.upload.clearFiles();
|
if(res.code == 1 && res.data) {
|
this.$message.success(res.msg);
|
}else {
|
this.$message.error(res.msg);
|
}
|
},
|
onError() {
|
this.loading = false;
|
this.$message.error("解析失败");
|
this.$refs.upload.clearFiles();
|
},
|
setBattData(data) {
|
this.battInfoDialog = false;
|
this.loading = true;
|
setTimeout(()=>{
|
this.loading = false;
|
this.params.batteryType = data.batteryType; // 电池类型
|
this.params.nominalCap = data.nominalCap; // 标称容量
|
this.params.nominalRes = data.nominalRes; // 标称内阻
|
this.params.initRes = data.initRes; // 实际内阻
|
this.params.hourRate= data.hourRate; // 放电小时率
|
this.params.fileName = data.fileName;
|
this.timeValue = ""; // 测试时间
|
this.formatData(data.list);
|
this.searchStanderLine();
|
}, 500);
|
|
},
|
formatData(data) {
|
let params = this.params;
|
this.$options.dischargeData = data;
|
this.isHasDischargeData = data.length;
|
let totalVol = [];
|
let totalCurr = [];
|
let dataTbl = [];
|
let num = 5;
|
let timeList = [];
|
for(let i=0; i<data.length; i++) {
|
let item = data[i];
|
if(i%num) {
|
continue;
|
}
|
let time = formatSeconds(item.testTimeLong);
|
timeList.push({
|
value: i,
|
label: time
|
});
|
let groupVol = Number(item.vcData.groupvol[0]).toHold(3)
|
totalVol.push(
|
[
|
time,
|
groupVol,
|
]
|
);
|
let groupCurr = (-Number(item.vcData.battcurr[0])).toFixed(1);
|
totalCurr.push(
|
[
|
time,
|
groupCurr,
|
]
|
);
|
|
dataTbl.push({
|
time: time,
|
groupVol: groupVol,
|
groupCurr: groupCurr,
|
});
|
}
|
this.$options.formatRs.totalVol = totalVol;
|
this.$options.formatRs.totalCurr = totalCurr;
|
this.$options.formatRs.dataTbl = dataTbl;
|
|
this.timeList = timeList;
|
this.timeValue = timeList[timeList.length-1].value;
|
// 设置表格数据
|
this.dataTbl = dataTbl;
|
|
let specialPoint = getSpecialPointIndex(
|
totalVol.map(item=>{
|
return item[1];
|
})
|
);
|
|
this.$options.specialPoint = specialPoint;
|
console.log(specialPoint);
|
// 设置是否存在驼峰锅底
|
this.isHasSpecial = specialPoint.code;
|
let markLine = {};
|
if (specialPoint.code) {
|
let qgth = getQgth(specialPoint, params.batteryType * params.monNum);
|
this.qgth = qgth;
|
markLine = {
|
data: [
|
{
|
label: {
|
show: true,
|
position: "end",
|
formatter: [
|
"{a|" + totalVol[specialPoint.min][0] + "}" + "{c|}",
|
"{b|锅底电压:" +totalVol[specialPoint.min][1] +"V}" +"{c|}",
|
].join("\n"),
|
rich: {
|
a: {},
|
b: {},
|
c: {
|
width: 60,
|
},
|
},
|
},
|
xAxis: totalVol[specialPoint.min][0],
|
},
|
{
|
label: {
|
show: true,
|
position: "end",
|
formatter: [
|
"{c|}" + "{a|" + totalVol[specialPoint.max][0] + "}",
|
"{c|}" +"{b|驼峰电压:" +totalVol[specialPoint.max][1] +"V}",
|
].join("\n"),
|
rich: {
|
a: {},
|
b: {},
|
c: {
|
width: 80,
|
},
|
},
|
},
|
xAxis: totalVol[specialPoint.max][0],
|
},
|
],
|
};
|
}
|
|
// 总电压
|
let totalVolOpt = this.$options.totalVolOpt();
|
totalVolOpt.title.text = this.qgth.title;
|
totalVolOpt.series[0].data = totalVol;
|
totalVolOpt.series[0].markLine = markLine;
|
this.$refs.totalVol.setOption(totalVolOpt);
|
|
// 总电流
|
let totalCurrOpt = this.$options.totalCurrOpt();
|
totalCurrOpt.series[0].data = totalCurr;
|
this.$refs.totalCurr.setOption(totalCurrOpt);
|
|
},
|
resize() {
|
this.$refs.totalCurr.resize();
|
this.$refs.totalVol.resize();
|
},
|
searchStanderLine() {
|
let dischargeData = this.$options.dischargeData;
|
let timeValue = this.timeValue;
|
let dischargeInfo = {
|
time: dischargeData[timeValue].testTimeLong,
|
value: dischargeData[timeValue].vcData.groupvol[0]
|
};
|
// 测试的组端电压数据
|
let testData = this.$options.dischargeData.map(item=>{
|
return {
|
time: item.testTimeLong,
|
value: item.vcData.groupvol[0]
|
}
|
});
|
dischargeInfo = getFirstTestData(dischargeInfo, this.$options.specialPoint, testData);
|
let params = this.params;
|
let monCap = this.params.nominalCap;
|
let c = params.hourRate+"c";
|
let va = params.batteryType+"v"+params.nominalCap+"ah";
|
this.params.realCap = "";
|
searchStandardLine(c, va).then(res=>{
|
let rs = res.data;
|
let data = [];
|
if(rs.code && rs.data) {
|
data = rs.data2;
|
this.isHasStandardLine = true;
|
}else {
|
this.isHasStandardLine = false;
|
}
|
// 格式化数据
|
this.$options.standardData = data.map(item=>{
|
return {
|
time: item.time,
|
timeNum: formatTime(item.time),
|
value: Number(item.value).toHold(2)
|
}
|
});
|
if(this.isHasStandardLine) {
|
this.params.realCap = getRealCapFromStandardLine(monCap, dischargeInfo.time, dischargeInfo.value, this.$options.standardData);
|
}
|
}).catch(error=>{
|
console.log(error);
|
this.$options.standardData = [];
|
this.isHasStandardLine = false;
|
});
|
},
|
},
|
computed: {
|
resPercent() {
|
let nominalRes = this.params.nominalRes;
|
let initRes = this.params.initRes;
|
if(nominalRes === "" || initRes === "") {
|
return "";
|
}else {
|
return (nominalRes/initRes*100).toHold(2);
|
}
|
},
|
capPercent() {
|
let nominalCap = this.params.nominalCap;
|
let realCap = this.params.realCap;
|
if(nominalCap === "" || realCap === "") {
|
return "";
|
}else {
|
return (realCap/nominalCap*100).toHold(0);
|
}
|
},
|
humpPotBottomPercent() {
|
if(this.isHasSpecial) {
|
let humpPotBottom = this.humpPotBottom;
|
// 获取驼峰锅底的比值
|
let qgthState = this.qgth.state;
|
let qgthPercent = humpPotBottom.normal;
|
switch (qgthState) {
|
case 0:
|
qgthPercent = humpPotBottom.abnormal;
|
break;
|
case 1:
|
qgthPercent = humpPotBottom.normal;
|
break;
|
case 2:
|
qgthPercent = humpPotBottom.mayBeAbnormal;
|
break;
|
default:
|
qgthPercent = "";
|
break;
|
}
|
return qgthPercent;
|
}
|
|
return "";
|
},
|
resultInfo() {
|
let value = "";
|
let label = "";
|
let dimensionWeight = this.dimensionWeight;
|
/**
|
* 存在条件
|
* 1.驼峰锅底比值
|
* 2.内阻比值
|
* 3.容量比值
|
*/
|
if(this.humpPotBottomPercent && this.resPercent && this.capPercent) {
|
value = (
|
this.humpPotBottomPercent*dimensionWeight.humpPotBottom
|
+this.resPercent*dimensionWeight.res
|
+this.capPercent*dimensionWeight.cap
|
)/100;
|
value = value.toHold(2);
|
}
|
let weight = Number(dimensionWeight.humpPotBottom)+Number(dimensionWeight.cap)+Number(dimensionWeight.res);
|
if(weight !== 100) {
|
value = "";
|
}
|
if(value !== "") {
|
if(value>=80) {
|
label = "优";
|
}else if(value<80 && value>=70) {
|
label = "良";
|
}else if(value<70 && value>=60) {
|
label = "较差";
|
}else {
|
label = "差";
|
}
|
}
|
|
return {
|
value,
|
label
|
}
|
},
|
errorMessage() {
|
let params = this.params;
|
if(!this.isHasDischargeData) {
|
return "请先导入数据";
|
}
|
|
if(!this.isHasSpecial) {
|
return "放电曲线中未获取到驼峰锅底";
|
}
|
let c = params.hourRate+"c";
|
let va = params.batteryType+"v"+params.nominalCap+"ah";
|
if(!this.isHasStandardLine) {
|
return "未找到对应的"+va+c+"标准曲线,请先上传对应的标准曲线";
|
}
|
let dimensionWeight = this.dimensionWeight;
|
let weight = Number(dimensionWeight.humpPotBottom)+Number(dimensionWeight.cap)+Number(dimensionWeight.res);
|
if(weight !== 100) {
|
return "维度权重和不等于100%";
|
}
|
|
|
return "";
|
}
|
},
|
mounted() {
|
this.$nextTick(()=>{
|
this.resize();
|
});
|
}
|
}
|
</script>
|
|
<style scoped>
|
.page-content {
|
height: 100%;
|
box-sizing: border-box;
|
}
|
.page-content-container {
|
height: 50%;
|
box-sizing: border-box;
|
padding: 4px;
|
}
|
.top-container {
|
display: inline-block;
|
width: 50%;
|
height: 100%;
|
box-sizing: border-box;
|
}
|
.top-container.left {
|
padding-right: 4px;
|
}
|
.top-container.right {
|
padding-left: 4px;
|
}
|
.upload-demo {
|
display: inline-block;
|
margin-left: 8px;
|
}
|
.table-container {
|
width: 100%;
|
border-collapse: collapse;
|
font-size: 14px;
|
}
|
.table-container td {
|
border: 1px solid #0ca7e2;
|
padding: 4px 4px;
|
text-align: center;
|
}
|
.error-message {
|
color: #f6f643;
|
}
|
</style>
|