@@ -1029,10 +1029,46 @@ function App() {
10291029 const todayEnergyHasData = todayEnergyPoints . some (
10301030 ( item ) => item . actual_battery_level !== null || item . predicted_battery_level !== null
10311031 ) ;
1032+ const prepareDashboardRefresh = React . useCallback ( ( ) => {
1033+ setDashboard ( null ) ;
1034+ setLoading ( true ) ;
1035+ setError ( null ) ;
1036+ } , [ ] ) ;
1037+ const changeCarId = React . useCallback (
1038+ ( nextCarId : number ) => {
1039+ prepareDashboardRefresh ( ) ;
1040+ setCarId ( nextCarId ) ;
1041+ setMobileControlsOpen ( false ) ;
1042+ } ,
1043+ [ prepareDashboardRefresh ]
1044+ ) ;
1045+ const changePeriod = React . useCallback (
1046+ ( nextPeriod : PeriodKey ) => {
1047+ prepareDashboardRefresh ( ) ;
1048+ setPeriod ( nextPeriod ) ;
1049+ if ( nextPeriod !== 'custom' ) setMobileControlsOpen ( false ) ;
1050+ } ,
1051+ [ prepareDashboardRefresh ]
1052+ ) ;
1053+ const changeCustomStart = React . useCallback (
1054+ ( value : string ) => {
1055+ prepareDashboardRefresh ( ) ;
1056+ setCustomStart ( value ) ;
1057+ } ,
1058+ [ prepareDashboardRefresh ]
1059+ ) ;
1060+ const changeCustomEnd = React . useCallback (
1061+ ( value : string ) => {
1062+ prepareDashboardRefresh ( ) ;
1063+ setCustomEnd ( value ) ;
1064+ } ,
1065+ [ prepareDashboardRefresh ]
1066+ ) ;
10321067 const refreshDashboard = React . useCallback ( ( ) => {
1068+ prepareDashboardRefresh ( ) ;
10331069 setRefreshKey ( ( key ) => key + 1 ) ;
10341070 setMobileControlsOpen ( false ) ;
1035- } , [ ] ) ;
1071+ } , [ prepareDashboardRefresh ] ) ;
10361072 const reportItems : Array < { key : ReportKey ; label : string ; icon : React . ReactNode } > = [
10371073 { key : 'overview' , label : '概览' , icon : < Activity size = { 17 } /> } ,
10381074 { key : 'trends' , label : '趋势' , icon : < ChartNoAxesColumn size = { 17 } /> } ,
@@ -1053,6 +1089,16 @@ function App() {
10531089 locations : '常到地点与充电地点' ,
10541090 vehicle : '车辆硬件、环境和软件信息'
10551091 } ;
1092+ const reportRenderKey = [
1093+ activeReport ,
1094+ carId ?? 'none' ,
1095+ dashboardQuery ,
1096+ chartPaletteKey ,
1097+ dashboard ?. data_window . first_seen_at ?? '' ,
1098+ dashboard ?. data_window . last_seen_at ?? '' ,
1099+ dashboard ?. data_window . since ?? '' ,
1100+ dashboard ?. data_window . until ?? ''
1101+ ] . join ( '|' ) ;
10561102
10571103 const renderDailyTrend = ( ) => (
10581104 < Section title = "日趋势" icon = { < ChartNoAxesColumn size = { 18 } /> } aside = { dashboard ?. data_window . since ? `${ shortDate ( dashboard . data_window . since ) } 起` : '全部' } >
@@ -1127,7 +1173,12 @@ function App() {
11271173 < Cell key = { entry . state } fill = { entry . fill } />
11281174 ) ) }
11291175 </ Pie >
1130- < Tooltip formatter = { chartTooltipFormatter ( { value : { label : '时长' , format : ( value ) => `${ n ( value ) } 小时` } } ) } />
1176+ < Tooltip
1177+ formatter = { ( value , name ) => {
1178+ const numeric = typeof value === 'number' ? value : Number ( value ) ;
1179+ return [ Number . isFinite ( numeric ) ? `${ n ( numeric ) } 小时` : '—' , String ( name ) ] ;
1180+ } }
1181+ />
11311182 </ PieChart >
11321183 </ ResponsiveContainer >
11331184 </ div >
@@ -1629,10 +1680,7 @@ function App() {
16291680 < span > 车辆</ span >
16301681 < select
16311682 value = { carId ?? '' }
1632- onChange = { ( event ) => {
1633- setCarId ( Number ( event . target . value ) ) ;
1634- setMobileControlsOpen ( false ) ;
1635- } }
1683+ onChange = { ( event ) => changeCarId ( Number ( event . target . value ) ) }
16361684 >
16371685 { cars . map ( ( item ) => (
16381686 < option value = { item . id } key = { item . id } >
@@ -1643,43 +1691,40 @@ function App() {
16431691 </ label >
16441692
16451693 < label className = "select-wrap drawer-field" >
1646- < span > 周期</ span >
1647- < select
1648- value = { period }
1649- onChange = { ( event ) => {
1650- setPeriod ( event . target . value as PeriodKey ) ;
1651- if ( event . target . value !== 'custom' ) setMobileControlsOpen ( false ) ;
1652- } }
1653- >
1654- { ranges . map ( ( item ) => (
1694+ < span > 图表配色</ span >
1695+ < select value = { chartPaletteKey } onChange = { ( event ) => setChartPaletteKey ( event . target . value as ChartPaletteKey ) } >
1696+ { chartPaletteOptions . map ( ( item ) => (
16551697 < option value = { item . value } key = { item . value } >
16561698 { item . label }
16571699 </ option >
16581700 ) ) }
16591701 </ select >
16601702 </ label >
1703+ < p className = "drawer-palette-detail" > { chartPalette . description } </ p >
16611704
16621705 < label className = "select-wrap drawer-field" >
1663- < span > 图表配色</ span >
1664- < select value = { chartPaletteKey } onChange = { ( event ) => setChartPaletteKey ( event . target . value as ChartPaletteKey ) } >
1665- { chartPaletteOptions . map ( ( item ) => (
1706+ < span > 周期</ span >
1707+ < select
1708+ value = { period }
1709+ onChange = { ( event ) => changePeriod ( event . target . value as PeriodKey ) }
1710+ >
1711+ { ranges . map ( ( item ) => (
16661712 < option value = { item . value } key = { item . value } >
16671713 { item . label }
16681714 </ option >
16691715 ) ) }
16701716 </ select >
16711717 </ label >
1672- < p className = "drawer-palette-detail" > { chartPalette . description } </ p >
16731718
16741719 { period === 'custom' ? (
16751720 < div className = "custom-period drawer-custom-period" >
16761721 < label >
16771722 < span > 开始</ span >
1678- < input type = "date" value = { customStart } max = { customEnd || undefined } onChange = { ( event ) => setCustomStart ( event . target . value ) } />
1723+ < input type = "date" value = { customStart } max = { customEnd || undefined } onChange = { ( event ) => changeCustomStart ( event . target . value ) } />
16791724 </ label >
16801725 < label >
16811726 < span > 结束</ span >
1682- < input type = "date" value = { customEnd } min = { customStart || undefined } onChange = { ( event ) => setCustomEnd ( event . target . value ) } />
1727+ < input type = "date" value = { customEnd } min = { customStart || undefined } onChange = { ( event ) => changeCustomEnd ( event . target . value ) } />
16831728 </ label >
16841729 </ div >
16851730 ) : null }
@@ -1694,7 +1739,7 @@ function App() {
16941739 < ReportTitle title = { reportItems . find ( ( item ) => item . key === activeReport ) ?. label ?? '报表' } description = { reportDescriptions [ activeReport ] } />
16951740 { error ? < div className = "alert" > { error } </ div > : null }
16961741
1697- { loading && ! dashboard ? < div className = "loading" > 加载中</ div > : renderCurrentReport ( ) }
1742+ { loading && ! dashboard ? < div className = "loading" > 加载中</ div > : < div key = { reportRenderKey } > { renderCurrentReport ( ) } </ div > }
16981743 </ main >
16991744 </ div >
17001745 ) ;
0 commit comments