food/src/components/BatteryStatus.vue
tk 0e231a5e91 【类 型】:fix 退出组件时 关闭settimeout 的实例
【原  因】:
【过  程】:
【影  响】:不销毁会叠加多次 settimeout

# 类型 包含:
# feat:新功能(feature)
# fix:修补bug
# docs:文档(documentation)
# style: 格式(不影响代码运行的变动)
# refactor:重构(即不是新增功能,也不是修改bug的代码变动)
# test:增加测试
# chore:构建过程或辅助工具的变动
2024-08-20 11:47:14 +08:00

198 lines
6.3 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>
<div class="w-100 batteryBar">
<!-- 进度条显示剩余电量 -->
<el-progress class="z90" :percentage="batteryRemaining" :show-text="false" :stroke-width="3"
:color="statusColor"></el-progress>
<!-- Tooltip 组件用于显示电量或续航时间 -->
<tooltip v-if="showTooltip" class="z90" :horizontalPosition="`${batteryRemaining}%`" :backgroundColor="statusColor">
<template v-if="showBattery">
{{ batteryRemainingPower }} mAh
</template>
<template v-else>
{{ endurance }} 分钟
</template>
</tooltip>
<!-- 当返航剩余电量大于 5 显示返航提示 -->
<tooltip v-if="rtlRemaining > 0" class="z90" :horizontalPosition="`${rtlRemaining}%`" backgroundColor="#ff3333">
</tooltip>
</div>
</template>
<script>
import Tooltip from '@/components/Tooltip'
import geodist from 'geodist'
export default {
name: 'BatteryStatus',
data () {
return {
showBattery: true, // 用于控制显示电量或续航时间
interval: null // 用于存储定时器 ID
}
},
computed: {
statusColor () {
// 获取剩余电量百分比和返航电量百分比
const remaining = this.batteryRemaining
const rtl = this.rtlRemaining
// 计算剩余电量与返航电量的差值
const percentage = remaining - rtl
// 将百分比值限制在 0 到 100 范围内
const normalizedPercentage = Math.max(0, Math.min(100, percentage))
// 定义起始和结束的色相值 (0 - 360)
const startHue = 200 // 代表 #00C8C8
const endHue = 0 // 代表 #FF0000
// 根据百分比计算色相
const hue = Math.round(startHue + (endHue - startHue) * (100 - normalizedPercentage) / 100)
// 设置饱和度和亮度(可以根据需要调整)
const saturation = 90 // 饱和度保持不变
const lightness = 50 // 亮度保持不变
// 返回 HSL 颜色值
return `hsl(${hue}, ${saturation}%, ${lightness}%)`
},
// 电池剩余电量值 (mAh)
batteryRemainingPower () {
if (this.plane && this.plane.planeState) {
const battCapacity = this.plane.planeState.battCapacity
const batteryRemaining = this.plane.planeState.batteryRemaining
if (battCapacity !== undefined && batteryRemaining !== undefined) {
return (battCapacity / 100) * batteryRemaining
}
}
return 0
},
// 剩余飞行时间 (分钟)
endurance () {
if (this.plane && this.plane.planeState && this.plane.planeState.currentBattery > 2) {
return Math.floor(this.batteryRemainingPower / 1000 / this.plane.planeState.currentBattery * 60)
}
return 0
},
// 控制 Tooltip 显示的条件
showTooltip () {
return this.batteryRemainingPower || this.endurance
},
// 剩余电量 (百分比)
batteryRemaining () {
if (this.plane && this.plane.planeState && this.plane.planeState.batteryRemaining !== undefined) {
const remaining = this.plane.planeState.batteryRemaining
if (remaining < 0) {
return 0
} else if (remaining > 100) {
return 100
} else {
return Number(remaining)
}
}
return 0
},
// 返航所需电量 (百分比)
rtlRemaining () {
let rtlTime = 0 // 返航所需时间(秒)
if (this.planePosition && this.homePosition && this.wpnavSpeed) {
const planeLngLat = { lat: this.planePosition[1], lon: this.planePosition[0] }
const homeLngLat = { lat: this.homePosition.lat, lon: this.homePosition.lng }
const horizontalDistance = geodist(planeLngLat, homeLngLat, { unit: 'meters' }) // 水平距离
const verticalDistance = Math.abs(this.planePosition[2] - this.homePosition.alt) // 垂直距离
const rtlDistance = horizontalDistance + verticalDistance // 返航总距离 水平+高度
rtlTime = Math.floor(Number(rtlDistance) / Number(this.wpnavSpeed)) // 返航需要时间 单位:秒
}
if (rtlTime <= 0) {
return 0
}
const currentBattery = this.plane.planeState.currentBattery // 电流 (安培)
const batteryCapacity = this.plane.planeState.battCapacity // 电池总容量 (mAh)
// 计算返航所需电量mAh假设电流与电量是线性关系
const rtlPowerRequired = rtlTime * currentBattery / 3.6 // 返航所需电量 (mAh)
// 计算返航所需电量占总电量的百分比
const rtlPowerPercentage = (rtlPowerRequired / batteryCapacity) * 100
// 将百分比限制在 0 到 100 范围内
return Math.max(0, Math.min(100, rtlPowerPercentage))
},
// 返航点
homePosition () {
if (this.plane && this.plane.planeState) {
return this.plane.planeState.homePosition
}
return null
},
// 飞机当前位置
planePosition () {
if (this.plane && this.plane.planeState) {
return this.plane.planeState.position[0]
}
return null
},
// 飞机返航速度
wpnavSpeed () {
if (this.plane && this.plane.planeState) {
return this.plane.planeState.wpnavSpeed
}
return null
}
},
props: {
plane: {
type: Object,
deep: true
}
},
components: {
Tooltip
},
methods: {
/**
* 剩余电量与剩余续航时间轮播
*/
startInterval () {
this.interval = setInterval(() => {
this.showBattery = !this.showBattery
}, 3000)
},
clearInterval () {
if (this.interval) {
clearInterval(this.interval)
this.interval = null
}
},
checkDisplayConditions () {
this.clearInterval()
// 如果存在剩余电量和剩余续航时间,则启动轮播
if (this.batteryRemainingPower > 0 && this.endurance > 0) {
this.startInterval()
}
}
},
watch: {
batteryRemainingPower () {
this.checkDisplayConditions()
},
endurance (val) {
this.checkDisplayConditions()
if (val === 0) {
this.showBattery = true
}
}
},
mounted () {
// 在组件挂载时检查显示条件
this.checkDisplayConditions()
},
destroyed () {
// 在组件销毁前清除定时器
this.clearInterval()
}
}
</script>
<style lang="scss" scoped>
@import "@/styles/theme.scss";
.batteryBar {
position: absolute;
}
</style>