276 lines
8.6 KiB
Vue
276 lines
8.6 KiB
Vue
<template>
|
|
<d2-container>
|
|
<template #header>
|
|
<div class="search-bar">
|
|
<el-form ref="searchForm" :inline="true" :model="search" size="mini">
|
|
<el-form-item :label="$t(key('battery_code'))" prop="battery_id">
|
|
<el-input
|
|
v-model.trim="search.battery_id"
|
|
:placeholder="$t(key('enter_battery_code'))"
|
|
clearable
|
|
style="width:240px"
|
|
@keyup.enter.native="fetchRecords"
|
|
/>
|
|
</el-form-item>
|
|
<el-form-item>
|
|
<el-button type="primary" icon="el-icon-search" :disabled="loading" @click="fetchRecords">
|
|
{{ $t(key('query')) }}
|
|
</el-button>
|
|
<el-button icon="el-icon-refresh" :disabled="loading" @click="resetSearch">
|
|
{{ $t(key('reset')) }}
|
|
</el-button>
|
|
</el-form-item>
|
|
</el-form>
|
|
</div>
|
|
</template>
|
|
|
|
<div v-loading="loading" class="curve-page">
|
|
<aside class="curve-list">
|
|
<el-empty v-if="records.length === 0" :description="$t(key('data_empty'))" :image-size="80" />
|
|
<el-menu v-else :default-active="String(activeIndex)" @select="selectRecord">
|
|
<el-menu-item v-for="(row, index) in records" :key="row.id || index" :index="String(index)">
|
|
<div class="curve-list__item">
|
|
<div>{{ $t(key('batch_name')) }}: {{ row.batch || '-' }}</div>
|
|
<div>{{ $t(key('process_name')) }}: {{ row.process_name || '-' }}</div>
|
|
<div>{{ $t(key('upload_time')) }}: {{ row.end_time || '-' }}</div>
|
|
</div>
|
|
</el-menu-item>
|
|
</el-menu>
|
|
</aside>
|
|
|
|
<main class="curve-content">
|
|
<div class="curve-toolbar">
|
|
<el-form :inline="true" size="mini" label-width="80px">
|
|
<el-form-item :label="$t(key('device_code'))">
|
|
<el-input :value="activeRecord.device_code || ''" disabled style="width:180px" />
|
|
</el-form-item>
|
|
<el-form-item :label="$t(key('battery_no'))">
|
|
<el-input :value="activeRecord.channel || ''" disabled style="width:180px" />
|
|
</el-form-item>
|
|
<el-form-item>
|
|
<el-button type="danger" icon="el-icon-download" :disabled="!activeRecord.id" @click="exportAllData">
|
|
{{ $t(key('export_all_data')) }}
|
|
</el-button>
|
|
<el-button type="warning" icon="el-icon-view" :disabled="!activeRecord.url" @click="viewFullTrayCurve">
|
|
{{ $t(key('view_full_tray_curve')) }}
|
|
</el-button>
|
|
</el-form-item>
|
|
</el-form>
|
|
</div>
|
|
<div ref="chart" class="curve-chart" />
|
|
</main>
|
|
</div>
|
|
</d2-container>
|
|
</template>
|
|
|
|
<script>
|
|
import * as echarts from 'echarts'
|
|
import { i18nMixin } from '@/composables/useI18n'
|
|
import {
|
|
exportBatteryCurveData,
|
|
getBatteryCurveData,
|
|
getBatteryCurveRecords
|
|
} from '@/api/data-platform/traceability/battery-curve'
|
|
|
|
export default {
|
|
name: 'data-platform-traceability-battery-curve',
|
|
mixins: [i18nMixin('page.data_platform.traceability.battery_curve')],
|
|
data () {
|
|
return {
|
|
loading: false,
|
|
chartLoading: false,
|
|
search: {
|
|
battery_id: ''
|
|
},
|
|
records: [],
|
|
activeIndex: -1,
|
|
chart: null,
|
|
xAxis: [],
|
|
seriesData: []
|
|
}
|
|
},
|
|
computed: {
|
|
activeRecord () {
|
|
return this.records[this.activeIndex] || {}
|
|
}
|
|
},
|
|
mounted () {
|
|
this.initChart()
|
|
window.addEventListener('resize', this.resizeChart)
|
|
},
|
|
beforeDestroy () {
|
|
window.removeEventListener('resize', this.resizeChart)
|
|
if (this.chart) this.chart.dispose()
|
|
},
|
|
methods: {
|
|
responseData (res) {
|
|
return res && res.data !== undefined ? res.data : res
|
|
},
|
|
initChart () {
|
|
this.chart = echarts.init(this.$refs.chart)
|
|
this.drawChart()
|
|
},
|
|
resizeChart () {
|
|
if (this.chart) this.chart.resize()
|
|
},
|
|
async fetchRecords () {
|
|
this.loading = true
|
|
try {
|
|
const res = await getBatteryCurveRecords({
|
|
...this.search,
|
|
action: 'battery_traceability_search'
|
|
})
|
|
const data = this.responseData(res)
|
|
this.records = Array.isArray(data) ? data : []
|
|
this.activeIndex = this.records.length ? 0 : -1
|
|
if (this.activeIndex > -1) {
|
|
await this.loadCurve(this.activeRecord.id)
|
|
} else {
|
|
this.xAxis = []
|
|
this.seriesData = []
|
|
this.drawChart()
|
|
}
|
|
} finally {
|
|
this.loading = false
|
|
}
|
|
},
|
|
resetSearch () {
|
|
this.search.battery_id = ''
|
|
this.records = []
|
|
this.activeIndex = -1
|
|
this.xAxis = []
|
|
this.seriesData = []
|
|
this.drawChart()
|
|
},
|
|
selectRecord (index) {
|
|
this.activeIndex = Number(index)
|
|
this.loadCurve(this.activeRecord.id)
|
|
},
|
|
async loadCurve (id) {
|
|
if (!id) return
|
|
this.chartLoading = true
|
|
if (this.chart) this.chart.showLoading()
|
|
try {
|
|
const res = await getBatteryCurveData({ id, action: 'batterycurveread' })
|
|
const data = this.responseData(res) || {}
|
|
if (Array.isArray(data)) {
|
|
this.xAxis = []
|
|
this.seriesData = []
|
|
} else {
|
|
this.xAxis = data.tm || []
|
|
this.seriesData = [
|
|
{ lineStyle: { normal: { width: 1 } }, name: this.$t(this.key('current')), type: 'line', symbolSize: 0, data: data.A || [] },
|
|
{ lineStyle: { normal: { width: 1 } }, yAxisIndex: 1, name: this.$t(this.key('voltage')), type: 'line', symbolSize: 0, data: data.V || [] },
|
|
{ lineStyle: { normal: { width: 1 } }, yAxisIndex: 2, name: this.$t(this.key('capacity')), type: 'bar', symbolSize: 0, data: data.C || [] }
|
|
]
|
|
}
|
|
this.drawChart()
|
|
} finally {
|
|
this.chartLoading = false
|
|
if (this.chart) this.chart.hideLoading()
|
|
}
|
|
},
|
|
drawChart () {
|
|
if (!this.chart) return
|
|
const option = {
|
|
title: { text: this.$t(this.key('data_chart')) },
|
|
tooltip: { trigger: 'axis' },
|
|
legend: {
|
|
data: [this.$t(this.key('current')), this.$t(this.key('voltage')), this.$t(this.key('capacity'))],
|
|
selected: {
|
|
[this.$t(this.key('current'))]: true,
|
|
[this.$t(this.key('voltage'))]: true,
|
|
[this.$t(this.key('capacity'))]: false
|
|
}
|
|
},
|
|
toolbox: { feature: { saveAsImage: {} } },
|
|
dataZoom: [
|
|
{ type: 'inside', xAxisIndex: [0], realtime: false },
|
|
{ type: 'inside', yAxisIndex: [0], realtime: false }
|
|
],
|
|
xAxis: { type: 'category', boundaryGap: false, data: this.xAxis, scale: false },
|
|
yAxis: [
|
|
{ type: 'value', scale: false, name: this.$t(this.key('current')), axisLabel: { formatter: '{value} mA' } },
|
|
{ type: 'value', scale: false, name: this.$t(this.key('voltage')), axisLabel: { formatter: '{value} mV' } },
|
|
{ type: 'value', scale: false, name: this.$t(this.key('capacity')), axisLabel: { formatter: '{value} mAH' }, position: 'right', offset: 80 }
|
|
],
|
|
series: this.seriesData
|
|
}
|
|
this.chart.setOption(option, true)
|
|
},
|
|
viewFullTrayCurve () {
|
|
if (this.activeRecord.url) window.location.href = this.activeRecord.url
|
|
},
|
|
async exportAllData () {
|
|
if (!this.activeRecord.id) return
|
|
const res = await exportBatteryCurveData({
|
|
id: this.activeRecord.id,
|
|
action: 'export_all_data'
|
|
})
|
|
const data = this.responseData(res)
|
|
if (!data) return
|
|
const link = document.createElement('a')
|
|
link.href = process.env.VUE_APP_PRO_PUBLIC_URL ? process.env.VUE_APP_PRO_PUBLIC_URL + data : data
|
|
link.target = '_blank'
|
|
document.body.appendChild(link)
|
|
link.click()
|
|
document.body.removeChild(link)
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.search-bar {
|
|
margin-bottom: -18px;
|
|
}
|
|
|
|
.curve-page {
|
|
display: grid;
|
|
grid-template-columns: 260px minmax(0, 1fr);
|
|
height: calc(100vh - 170px);
|
|
min-height: 560px;
|
|
border: 1px solid #ebeef5;
|
|
}
|
|
|
|
.curve-list {
|
|
overflow: auto;
|
|
border-right: 1px solid #ebeef5;
|
|
background: #fff;
|
|
}
|
|
|
|
.curve-list__item {
|
|
width: 100%;
|
|
overflow: hidden;
|
|
line-height: 1.5;
|
|
white-space: normal;
|
|
word-break: break-all;
|
|
}
|
|
|
|
.curve-list ::v-deep .el-menu-item {
|
|
height: auto;
|
|
min-height: 86px;
|
|
padding: 8px 12px !important;
|
|
line-height: 1.5;
|
|
}
|
|
|
|
.curve-content {
|
|
min-width: 0;
|
|
padding: 12px;
|
|
background: #fafafa;
|
|
}
|
|
|
|
.curve-toolbar {
|
|
margin-bottom: 12px;
|
|
padding-bottom: 10px;
|
|
border-bottom: 1px solid #ebeef5;
|
|
}
|
|
|
|
.curve-chart {
|
|
height: calc(100% - 64px);
|
|
min-height: 430px;
|
|
border: 1px solid #ebeef5;
|
|
background: #fff;
|
|
}
|
|
</style>
|