feat: persist hydrogen order pages

This commit is contained in:
kkfluous
2026-08-07 17:19:34 +08:00
parent d786b984bb
commit 18287a2c70
4 changed files with 49 additions and 12 deletions
+14
View File
@@ -117,6 +117,7 @@ export default function HydrogenDaily() {
startDate: nextRange.start, startDate: nextRange.start,
endDate: nextRange.end, endDate: nextRange.end,
selectedDate: undefined, selectedDate: undefined,
orderPage: undefined,
}, 'replace'); }, 'replace');
}; };
@@ -132,6 +133,7 @@ export default function HydrogenDaily() {
startDate: normalized.start, startDate: normalized.start,
endDate: normalized.end, endDate: normalized.end,
selectedDate: undefined, selectedDate: undefined,
orderPage: undefined,
}, 'replace'); }, 'replace');
}; };
@@ -142,6 +144,7 @@ export default function HydrogenDaily() {
vehicleScope: next, vehicleScope: next,
startDate: effectiveRange.start, startDate: effectiveRange.start,
endDate: effectiveRange.end, endDate: effectiveRange.end,
orderPage: undefined,
}, 'replace'); }, 'replace');
}; };
@@ -162,6 +165,7 @@ export default function HydrogenDaily() {
startDate: effectiveRange.start, startDate: effectiveRange.start,
endDate: effectiveRange.end, endDate: effectiveRange.end,
selectedDate: date, selectedDate: date,
orderPage: undefined,
}, 'push'); }, 'push');
}; };
@@ -172,9 +176,17 @@ export default function HydrogenDaily() {
startDate: effectiveRange.start, startDate: effectiveRange.start,
endDate: effectiveRange.end, endDate: effectiveRange.end,
selectedDate: undefined, selectedDate: undefined,
orderPage: undefined,
}, 'replace'); }, 'replace');
}; };
const changeOrderPage = useCallback((page: number, mode: 'push' | 'replace') => {
commitDrillContext({
...drillContext,
orderPage: page > 1 ? page : undefined,
}, mode);
}, [commitDrillContext, drillContext]);
const retryLoad = () => { const retryLoad = () => {
setRows(null); setRows(null);
setError(null); setError(null);
@@ -388,9 +400,11 @@ export default function HydrogenDaily() {
<HydrogenOrders <HydrogenOrders
date={selectedDate} date={selectedDate}
dailyRow={selectedDailyRow} dailyRow={selectedDailyRow}
page={drillContext.orderPage ?? 1}
vehicleScope={vehicleScope} vehicleScope={vehicleScope}
stationId={selectedStationId} stationId={selectedStationId}
customerName={selectedCustomerName} customerName={selectedCustomerName}
onPageChange={changeOrderPage}
onClose={closeOrders} onClose={closeOrders}
/> />
)} )}
+15 -9
View File
@@ -13,41 +13,47 @@ function fmtMoney(value: number): string {
export default function HydrogenOrders({ export default function HydrogenOrders({
date, date,
dailyRow, dailyRow,
page,
vehicleScope, vehicleScope,
stationId, stationId,
customerName, customerName,
onPageChange,
onClose, onClose,
}: { }: {
date: string; date: string;
dailyRow?: HydrogenDailyRow; dailyRow?: HydrogenDailyRow;
page: number;
vehicleScope: CustomerType; vehicleScope: CustomerType;
stationId?: number; stationId?: number;
customerName?: string; customerName?: string;
onPageChange: (page: number, mode: 'push' | 'replace') => void;
onClose: () => void; onClose: () => void;
}) { }) {
const [page, setPage] = useState(1);
const [data, setData] = useState<HydrogenOrderResponse | null>(null); const [data, setData] = useState<HydrogenOrderResponse | null>(null);
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null); const [error, setError] = useState<string | null>(null);
const [retryKey, setRetryKey] = useState(0); const [retryKey, setRetryKey] = useState(0);
useEffect(() => {
setPage(1);
}, [vehicleScope, customerName, date, stationId]);
useEffect(() => { useEffect(() => {
let cancelled = false; let cancelled = false;
setLoading(true); setLoading(true);
setError(null); setError(null);
setData(null); setData(null);
fetchHydrogenOrders({ date, customer: vehicleScope, stationId, customerName, page, limit: 20 }) fetchHydrogenOrders({ date, customer: vehicleScope, stationId, customerName, page, limit: 20 })
.then(result => { if (!cancelled) setData(result); }) .then(result => {
if (cancelled) return;
if (page > result.totalPages) {
onPageChange(result.totalPages, 'replace');
return;
}
setData(result);
})
.catch(loadError => { .catch(loadError => {
if (!cancelled) setError(loadError instanceof Error ? loadError.message : String(loadError)); if (!cancelled) setError(loadError instanceof Error ? loadError.message : String(loadError));
}) })
.finally(() => { if (!cancelled) setLoading(false); }); .finally(() => { if (!cancelled) setLoading(false); });
return () => { cancelled = true; }; return () => { cancelled = true; };
}, [vehicleScope, customerName, date, page, retryKey, stationId]); }, [vehicleScope, customerName, date, onPageChange, page, retryKey, stationId]);
const totalPages = data?.totalPages ?? 1; const totalPages = data?.totalPages ?? 1;
const scope = customerName const scope = customerName
@@ -165,8 +171,8 @@ export default function HydrogenOrders({
<footer className="flex items-center justify-between border-t border-slate-100 px-3 py-3 md:px-4"> <footer className="flex items-center justify-between border-t border-slate-100 px-3 py-3 md:px-4">
<span className="text-[10px] font-bold text-slate-400"> {page} / {totalPages} </span> <span className="text-[10px] font-bold text-slate-400"> {page} / {totalPages} </span>
<div className="flex gap-2"> <div className="flex gap-2">
<button type="button" onClick={() => setPage(current => Math.max(1, current - 1))} disabled={page <= 1 || loading} className="flex h-8 w-8 items-center justify-center rounded-lg border border-slate-200 text-slate-500 disabled:opacity-30" aria-label="上一页加氢订单" title="上一页"><ChevronLeft size={14} /></button> <button type="button" onClick={() => onPageChange(Math.max(1, page - 1), 'push')} disabled={page <= 1 || loading} className="flex h-8 w-8 items-center justify-center rounded-lg border border-slate-200 text-slate-500 disabled:opacity-30" aria-label="上一页加氢订单" title="上一页"><ChevronLeft size={14} /></button>
<button type="button" onClick={() => setPage(current => Math.min(totalPages, current + 1))} disabled={page >= totalPages || loading} className="flex h-8 w-8 items-center justify-center rounded-lg border border-slate-200 text-slate-500 disabled:opacity-30" aria-label="下一页加氢订单" title="下一页"><ChevronRight size={14} /></button> <button type="button" onClick={() => onPageChange(Math.min(totalPages, page + 1), 'push')} disabled={page >= totalPages || loading} className="flex h-8 w-8 items-center justify-center rounded-lg border border-slate-200 text-slate-500 disabled:opacity-30" aria-label="下一页加氢订单" title="下一页"><ChevronRight size={14} /></button>
</div> </div>
</footer> </footer>
) : null} ) : null}
@@ -82,20 +82,30 @@ test('clears station parameters when returning to overview', () => {
assert.equal(url, '/energy?company=5&hydrogenScope=lingniu#hydrogen'); assert.equal(url, '/energy?company=5&hydrogenScope=lingniu#hydrogen');
}); });
test('preserves a selected order date in the hydrogen analysis URL', () => { test('preserves a selected order date and page in the hydrogen analysis URL', () => {
const context = parseHydrogenDrillContext( const context = parseHydrogenDrillContext(
'?hydrogenScope=lingniu&hydrogenStart=2026-08-01&hydrogenEnd=2026-08-07&hydrogenDate=2026-08-05', '?hydrogenScope=lingniu&hydrogenStart=2026-08-01&hydrogenEnd=2026-08-07&hydrogenDate=2026-08-05&hydrogenPage=3',
); );
assert.equal(context.selectedDate, '2026-08-05'); assert.equal(context.selectedDate, '2026-08-05');
assert.equal(context.orderPage, 3);
assert.equal( assert.equal(
buildHydrogenDrillUrl( buildHydrogenDrillUrl(
{ pathname: '/energy', search: '?company=5', hash: '#hydrogen' }, { pathname: '/energy', search: '?company=5', hash: '#hydrogen' },
context, context,
), ),
'/energy?company=5&hydrogenScope=lingniu&hydrogenStart=2026-08-01&hydrogenEnd=2026-08-07&hydrogenDate=2026-08-05#hydrogen', '/energy?company=5&hydrogenScope=lingniu&hydrogenStart=2026-08-01&hydrogenEnd=2026-08-07&hydrogenDate=2026-08-05&hydrogenPage=3#hydrogen',
); );
assert.equal( assert.equal(
parseHydrogenDrillContext('?hydrogenStart=2026-08-01&hydrogenEnd=2026-08-07&hydrogenDate=2026-08-08').selectedDate, parseHydrogenDrillContext('?hydrogenStart=2026-08-01&hydrogenEnd=2026-08-07&hydrogenDate=2026-08-08').selectedDate,
undefined, undefined,
); );
assert.equal(parseHydrogenDrillContext('?hydrogenPage=3').orderPage, undefined);
assert.equal(parseHydrogenDrillContext('?hydrogenDate=2026-08-05&hydrogenPage=0').orderPage, undefined);
assert.equal(
buildHydrogenDrillUrl(
{ pathname: '/energy', search: '', hash: '#hydrogen' },
{ level: 'overview', vehicleScope: 'lingniu', orderPage: 3 },
),
'/energy?hydrogenScope=lingniu#hydrogen',
);
}); });
@@ -12,6 +12,7 @@ export interface HydrogenDrillContext {
startDate?: string; startDate?: string;
endDate?: string; endDate?: string;
selectedDate?: string; selectedDate?: string;
orderPage?: number;
} }
interface LocationParts { interface LocationParts {
@@ -74,6 +75,8 @@ export function parseHydrogenDrillContext(search: string): HydrogenDrillContext
const rangeEnd = startDate && endDate ? (startDate <= endDate ? endDate : startDate) : undefined; const rangeEnd = startDate && endDate ? (startDate <= endDate ? endDate : startDate) : undefined;
if (selectedDate && (!rangeStart || !rangeEnd || (selectedDate >= rangeStart && selectedDate <= rangeEnd))) { if (selectedDate && (!rangeStart || !rangeEnd || (selectedDate >= rangeStart && selectedDate <= rangeEnd))) {
context.selectedDate = selectedDate; context.selectedDate = selectedDate;
const orderPage = positiveInteger(params.get('hydrogenPage'));
if (orderPage && orderPage > 1) context.orderPage = orderPage;
} }
return context; return context;
} }
@@ -93,6 +96,7 @@ export function buildHydrogenDrillUrl(
'hydrogenStart', 'hydrogenStart',
'hydrogenEnd', 'hydrogenEnd',
'hydrogenDate', 'hydrogenDate',
'hydrogenPage',
]) { ]) {
params.delete(key); params.delete(key);
} }
@@ -110,6 +114,9 @@ export function buildHydrogenDrillUrl(
if (context.startDate) params.set('hydrogenStart', context.startDate); if (context.startDate) params.set('hydrogenStart', context.startDate);
if (context.endDate) params.set('hydrogenEnd', context.endDate); if (context.endDate) params.set('hydrogenEnd', context.endDate);
if (context.selectedDate) params.set('hydrogenDate', context.selectedDate); if (context.selectedDate) params.set('hydrogenDate', context.selectedDate);
if (context.selectedDate && context.orderPage && context.orderPage > 1) {
params.set('hydrogenPage', String(context.orderPage));
}
const query = params.toString(); const query = params.toString();
return `${location.pathname}${query ? `?${query}` : ''}${location.hash}`; return `${location.pathname}${query ? `?${query}` : ''}${location.hash}`;