@@ -162,6 +162,8 @@ type RangePoint = {
162162type TodayEnergyPoint = {
163163 hour : number ;
164164 label : string ;
165+ actual_battery_level ?: number | null ;
166+ predicted_battery_level ?: number | null ;
165167 actual_kwh ?: number | null ;
166168 actual_drive_kwh ?: number | null ;
167169 actual_asleep_kwh ?: number | null ;
@@ -182,6 +184,8 @@ type TodayEnergy = {
182184 state ?: string | null ;
183185 prediction_basis ?: string | null ;
184186 prediction_confidence ?: string | null ;
187+ current_battery_level ?: number | null ;
188+ estimated_end_battery_level ?: number | null ;
185189 actual_kwh ?: number | null ;
186190 predicted_remaining_kwh ?: number | null ;
187191 estimated_total_kwh ?: number | null ;
@@ -390,11 +394,6 @@ function kwh(value: number | null | undefined): string {
390394 return value === null || value === undefined ? '—' : `${ numberFormat . format ( value ) } kWh` ;
391395}
392396
393- function preciseKwh ( value : number | null | undefined ) : string {
394- if ( value === null || value === undefined ) return '—' ;
395- return `${ new Intl . NumberFormat ( 'zh-CN' , { maximumFractionDigits : 2 } ) . format ( value ) } kWh` ;
396- }
397-
398397function percent ( value : number | null | undefined ) : string {
399398 return value === null || value === undefined ? '—' : `${ integerFormat . format ( value ) } %` ;
400399}
@@ -895,29 +894,16 @@ function App() {
895894 ( ) =>
896895 ( dashboard ?. today_energy ?. points ?? [ ] ) . map ( ( item ) => ( {
897896 ...item ,
898- hourLabel : String ( item . hour ) . padStart ( 2 , '0' ) ,
899- actual_kwh : Number ( ( item . actual_kwh ?? 0 ) . toFixed ( 2 ) ) ,
900- actual_drive_kwh : Number ( ( item . actual_drive_kwh ?? 0 ) . toFixed ( 2 ) ) ,
901- actual_asleep_kwh : Number ( ( item . actual_asleep_kwh ?? 0 ) . toFixed ( 2 ) ) ,
902- actual_awake_kwh : Number ( ( item . actual_awake_kwh ?? 0 ) . toFixed ( 2 ) ) ,
903- actual_unknown_kwh : Number ( ( item . actual_unknown_kwh ?? 0 ) . toFixed ( 2 ) ) ,
904- predicted_drive_kwh : Number ( ( item . predicted_drive_kwh ?? 0 ) . toFixed ( 2 ) ) ,
905- predicted_asleep_kwh : Number ( ( item . predicted_asleep_kwh ?? 0 ) . toFixed ( 2 ) ) ,
906- predicted_awake_kwh : Number ( ( item . predicted_awake_kwh ?? 0 ) . toFixed ( 2 ) ) ,
907- predicted_unknown_kwh : Number ( ( item . predicted_unknown_kwh ?? 0 ) . toFixed ( 2 ) )
897+ hourLabel : item . hour === 24 ? '24' : String ( item . hour ) . padStart ( 2 , '0' ) ,
898+ actual_battery_level :
899+ item . actual_battery_level === null || item . actual_battery_level === undefined ? null : Number ( item . actual_battery_level . toFixed ( 1 ) ) ,
900+ predicted_battery_level :
901+ item . predicted_battery_level === null || item . predicted_battery_level === undefined ? null : Number ( item . predicted_battery_level . toFixed ( 1 ) )
908902 } ) ) ,
909903 [ dashboard ]
910904 ) ;
911905 const todayEnergyHasData = todayEnergyPoints . some (
912- ( item ) =>
913- item . actual_drive_kwh ||
914- item . actual_asleep_kwh ||
915- item . actual_awake_kwh ||
916- item . actual_unknown_kwh ||
917- item . predicted_drive_kwh ||
918- item . predicted_asleep_kwh ||
919- item . predicted_awake_kwh ||
920- item . predicted_unknown_kwh
906+ ( item ) => item . actual_battery_level !== null || item . predicted_battery_level !== null
921907 ) ;
922908 const reportItems : Array < { key : ReportKey ; label : string ; icon : React . ReactNode } > = [
923909 { key : 'overview' , label : '概览' , icon : < Activity size = { 17 } /> } ,
@@ -1039,57 +1025,41 @@ function App() {
10391025 const aside = `${ basis } · 最近 ${ energy ?. history_days ?? 30 } 天均值${ energy ?. prediction_confidence === 'low' ? ' · 样本较少' : '' } ` ;
10401026
10411027 return (
1042- < Section title = "今日电量消耗" icon = { < BatteryCharging size = { 18 } /> } aside = { aside } >
1043- < div className = "today-energy-kpis" >
1044- < div >
1045- < span > 已消耗</ span >
1046- < strong > { preciseKwh ( energy ?. actual_kwh ) } </ strong >
1047- </ div >
1048- < div >
1049- < span > 预计剩余</ span >
1050- < strong > { preciseKwh ( energy ?. predicted_remaining_kwh ) } </ strong >
1051- </ div >
1028+ < Section title = "今日电量预测" icon = { < BatteryCharging size = { 18 } /> } aside = { aside } >
1029+ < div className = "today-energy-kpis today-energy-kpis-single" >
10521030 < div >
1053- < span > 预计全天 </ span >
1054- < strong > { preciseKwh ( energy ?. estimated_total_kwh ) } </ strong >
1031+ < span > 预计今日结束电量 </ span >
1032+ < strong > { percent ( energy ?. estimated_end_battery_level ) } </ strong >
10551033 </ div >
10561034 </ div >
10571035
10581036 { todayEnergyHasData ? (
10591037 < >
10601038 < div className = "chart chart-compact today-energy-chart" >
10611039 < ResponsiveContainer width = "100%" height = "100%" >
1062- < BarChart data = { todayEnergyPoints } margin = { { top : 10 , right : 8 , bottom : 0 , left : - 20 } } >
1040+ < LineChart data = { todayEnergyPoints } margin = { { top : 10 , right : 10 , bottom : 0 , left : - 16 } } >
10631041 < CartesianGrid strokeDasharray = "3 3" vertical = { false } />
10641042 < XAxis dataKey = "hourLabel" tickLine = { false } axisLine = { false } interval = { 2 } />
1065- < YAxis tickLine = { false } axisLine = { false } width = { 40 } />
1043+ < YAxis tickLine = { false } axisLine = { false } width = { 38 } domain = { [ 0 , 100 ] } tickFormatter = { ( value ) => ` ${ value } %` } />
10661044 < Tooltip
10671045 formatter = { chartTooltipFormatter ( {
1068- actual_kwh : { label : '已消耗' , format : preciseKwh } ,
1069- predicted_drive_kwh : { label : '预计行驶' , format : preciseKwh } ,
1070- predicted_asleep_kwh : { label : '预计休眠' , format : preciseKwh } ,
1071- predicted_awake_kwh : { label : '预计未休眠' , format : preciseKwh } ,
1072- predicted_unknown_kwh : { label : '预计未知' , format : preciseKwh }
1046+ actual_battery_level : { label : '实际电量' , format : percent } ,
1047+ predicted_battery_level : { label : '预测电量' , format : percent }
10731048 } ) }
10741049 labelFormatter = { ( label ) => `${ label } :00` }
10751050 />
1076- < Bar dataKey = "actual_kwh" stackId = "energy" fill = "#171a20" radius = { [ 3 , 3 , 0 , 0 ] } name = "actual_kwh" />
1077- < Bar dataKey = "predicted_drive_kwh" stackId = "energy" fill = "#8da2fb" radius = { [ 3 , 3 , 0 , 0 ] } name = "predicted_drive_kwh" />
1078- < Bar dataKey = "predicted_asleep_kwh" stackId = "energy" fill = "#94a3b8" radius = { [ 3 , 3 , 0 , 0 ] } name = "predicted_asleep_kwh" />
1079- < Bar dataKey = "predicted_awake_kwh" stackId = "energy" fill = "#3e6ae1" fillOpacity = { 0.62 } radius = { [ 3 , 3 , 0 , 0 ] } name = "predicted_awake_kwh" />
1080- < Bar dataKey = "predicted_unknown_kwh" stackId = "energy" fill = "#d8d9da" radius = { [ 3 , 3 , 0 , 0 ] } name = "predicted_unknown_kwh" />
1081- </ BarChart >
1051+ < Line type = "monotone" dataKey = "actual_battery_level" stroke = "#171a20" strokeWidth = { 2.4 } dot = { false } connectNulls = { false } name = "实际电量" />
1052+ < Line type = "monotone" dataKey = "predicted_battery_level" stroke = "#3e6ae1" strokeWidth = { 2.4 } strokeDasharray = "6 4" dot = { false } connectNulls = { false } name = "预测电量" />
1053+ </ LineChart >
10821054 </ ResponsiveContainer >
10831055 </ div >
1084- < div className = "energy-legend" aria-label = "今日电量消耗图例" >
1085- < span > < i style = { { background : '#171a20' } } /> 已消耗</ span >
1086- < span > < i style = { { background : '#8da2fb' } } /> 预计行驶</ span >
1087- < span > < i style = { { background : '#94a3b8' } } /> 预计休眠</ span >
1088- < span > < i style = { { background : '#3e6ae1' } } /> 预计未休眠</ span >
1056+ < div className = "energy-legend" aria-label = "今日电量预测图例" >
1057+ < span > < i style = { { background : '#171a20' } } /> 实际电量</ span >
1058+ < span > < i style = { { background : '#3e6ae1' } } /> 预测电量</ span >
10891059 </ div >
10901060 </ >
10911061 ) : (
1092- < Empty text = "暂无可计算的今日能耗采样 " />
1062+ < Empty text = "暂无可计算的今日电量采样 " />
10931063 ) }
10941064 </ Section >
10951065 ) ;
0 commit comments