fix: preserve electric drilldown history
This commit is contained in:
@@ -163,6 +163,7 @@ SUM(fee) / NULLIF(SUM(kwh), 0)
|
|||||||
- 已完成氢能每日趋势到加氢订单的 URL 下钻、分页和结构化故障状态;待数据源恢复后验收真实明细。
|
- 已完成氢能每日趋势到加氢订单的 URL 下钻、分页和结构化故障状态;待数据源恢复后验收真实明细。
|
||||||
- 已为电能总览与氢能每日趋势柱图统一 Enter/Space 键盘下钻;氢能有效日期柱提供可读名称、焦点和选中反馈。
|
- 已为电能总览与氢能每日趋势柱图统一 Enter/Space 键盘下钻;氢能有效日期柱提供可读名称、焦点和选中反馈。
|
||||||
- 已完成电能全部车辆、日期和订单下钻。
|
- 已完成电能全部车辆、日期和订单下钻。
|
||||||
|
- 电能每日列表打开新日期订单使用浏览器历史 `pushState`,返回/前进可恢复进入前后的分析状态;筛选调整仍使用 `replaceState`。
|
||||||
- 已完成 ETC 通行记录与结算账单下钻代码、筛选、分页和未同步空状态;待首次真实同步后验收真实数据。
|
- 已完成 ETC 通行记录与结算账单下钻代码、筛选、分页和未同步空状态;待首次真实同步后验收真实数据。
|
||||||
|
|
||||||
### 阶段 C:数据可信度
|
### 阶段 C:数据可信度
|
||||||
|
|||||||
@@ -58,9 +58,9 @@ export default function ElectricDaily() {
|
|||||||
const selectedDateRef = useRef(selectedDate);
|
const selectedDateRef = useRef(selectedDate);
|
||||||
selectedDateRef.current = selectedDate;
|
selectedDateRef.current = selectedDate;
|
||||||
|
|
||||||
const commitDrillContext = useCallback((next: ElectricDrillContext) => {
|
const commitDrillContext = useCallback((next: ElectricDrillContext, mode: 'push' | 'replace' = 'replace') => {
|
||||||
const url = buildElectricDrillUrl(window.location, next);
|
const url = buildElectricDrillUrl(window.location, next);
|
||||||
window.history.replaceState(null, '', url);
|
window.history[mode === 'push' ? 'pushState' : 'replaceState'](null, '', url);
|
||||||
setDrillContext(next);
|
setDrillContext(next);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
@@ -148,13 +148,14 @@ export default function ElectricDaily() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const toggleDate = (date: string) => {
|
const toggleDate = (date: string) => {
|
||||||
|
const opening = selectedDate !== date;
|
||||||
commitDrillContext({
|
commitDrillContext({
|
||||||
...drillContext,
|
...drillContext,
|
||||||
vehicleScope,
|
vehicleScope,
|
||||||
startDate: effectiveRange.start,
|
startDate: effectiveRange.start,
|
||||||
endDate: effectiveRange.end,
|
endDate: effectiveRange.end,
|
||||||
selectedDate: selectedDate === date ? undefined : date,
|
selectedDate: opening ? date : undefined,
|
||||||
});
|
}, opening ? 'push' : 'replace');
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -251,10 +252,13 @@ export default function ElectricDaily() {
|
|||||||
return (
|
return (
|
||||||
<div key={m.month} className="border-t border-slate-100 first:border-t-0">
|
<div key={m.month} className="border-t border-slate-100 first:border-t-0">
|
||||||
<button
|
<button
|
||||||
|
type="button"
|
||||||
onClick={() => toggleMonth(m.month)}
|
onClick={() => toggleMonth(m.month)}
|
||||||
className={`w-full grid grid-cols-[minmax(0,1fr)_120px_88px] md:grid-cols-[minmax(0,1fr)_160px_120px] gap-3 px-3 py-2.5 text-left transition-colors ${
|
className={`w-full grid grid-cols-[minmax(0,1fr)_120px_88px] md:grid-cols-[minmax(0,1fr)_160px_120px] gap-3 px-3 py-2.5 text-left transition-colors ${
|
||||||
open ? 'bg-blue-50/30' : 'hover:bg-slate-50'
|
open ? 'bg-blue-50/30' : 'hover:bg-slate-50'
|
||||||
}`}
|
}`}
|
||||||
|
aria-expanded={open}
|
||||||
|
aria-controls={open ? `electric-month-${m.month}` : undefined}
|
||||||
>
|
>
|
||||||
<span className="flex items-center gap-1 text-[12px] text-slate-700 font-bold">
|
<span className="flex items-center gap-1 text-[12px] text-slate-700 font-bold">
|
||||||
<ChevronRight size={14} className={`transition-transform ${open ? 'rotate-90' : ''} text-slate-400`} />
|
<ChevronRight size={14} className={`transition-transform ${open ? 'rotate-90' : ''} text-slate-400`} />
|
||||||
@@ -268,6 +272,7 @@ export default function ElectricDaily() {
|
|||||||
<AnimatePresence initial={false}>
|
<AnimatePresence initial={false}>
|
||||||
{open && (
|
{open && (
|
||||||
<motion.div
|
<motion.div
|
||||||
|
id={`electric-month-${m.month}`}
|
||||||
initial={{ height: 0, opacity: 0 }}
|
initial={{ height: 0, opacity: 0 }}
|
||||||
animate={{ height: 'auto', opacity: 1 }}
|
animate={{ height: 'auto', opacity: 1 }}
|
||||||
exit={{ height: 0, opacity: 0 }}
|
exit={{ height: 0, opacity: 0 }}
|
||||||
@@ -286,6 +291,7 @@ export default function ElectricDaily() {
|
|||||||
onClick={() => toggleDate(d.date)}
|
onClick={() => toggleDate(d.date)}
|
||||||
className={`grid w-full grid-cols-[minmax(0,1fr)_120px_88px] gap-3 px-3 py-2 pl-9 text-left md:grid-cols-[minmax(0,1fr)_160px_120px] ${abnormalBg}`}
|
className={`grid w-full grid-cols-[minmax(0,1fr)_120px_88px] gap-3 px-3 py-2 pl-9 text-left md:grid-cols-[minmax(0,1fr)_160px_120px] ${abnormalBg}`}
|
||||||
aria-expanded={selectedDate === d.date}
|
aria-expanded={selectedDate === d.date}
|
||||||
|
aria-controls={selectedDate === d.date ? `electric-orders-${d.date}` : undefined}
|
||||||
>
|
>
|
||||||
<span className="flex items-center gap-1 text-[12px] font-bold text-slate-600">
|
<span className="flex items-center gap-1 text-[12px] font-bold text-slate-600">
|
||||||
<ChevronRight size={12} className={`text-slate-400 transition-transform ${selectedDate === d.date ? 'rotate-90' : ''}`} />
|
<ChevronRight size={12} className={`text-slate-400 transition-transform ${selectedDate === d.date ? 'rotate-90' : ''}`} />
|
||||||
@@ -297,7 +303,7 @@ export default function ElectricDaily() {
|
|||||||
<span className="text-right"><TrendBadge value={d.chainPct} /></span>
|
<span className="text-right"><TrendBadge value={d.chainPct} /></span>
|
||||||
</button>
|
</button>
|
||||||
{selectedDate === d.date && (
|
{selectedDate === d.date && (
|
||||||
<div className="border-t border-blue-100 bg-blue-50/40 px-3 py-3 md:pl-9">
|
<div id={`electric-orders-${d.date}`} className="border-t border-blue-100 bg-blue-50/40 px-3 py-3 md:pl-9">
|
||||||
{ordersError ? (
|
{ordersError ? (
|
||||||
<ErrorState message={ordersError} variant="inline" />
|
<ErrorState message={ordersError} variant="inline" />
|
||||||
) : !orders || orders.date !== d.date ? (
|
) : !orders || orders.date !== d.date ? (
|
||||||
|
|||||||
Reference in New Issue
Block a user