重构(会员弹层):抽取 resolveRovingIndex 复用方向键索引

- 页签列表与泥点档位网格共用同一个 roving index 解析函数
- 用 switch 取代深层嵌套三元,Home/End/左右键语义保持不变
This commit is contained in:
2026-10-04 10:31:52 +08:00
parent 987e82605b
commit 93837a736d
@@ -36,6 +36,32 @@ import { resolveMembershipProductId } from './membershipProduct';
const WECHAT_NATIVE_PAY_QR_IMAGE_SIZE = 180;
/**
* roving tabindex / radiogroup 的方向键索引解析:`Home` / `End` 跳首尾,左右键循环,
* 其余按键返回 `null`(调用方据此忽略事件)。`currentIndex` 允许为 `-1`(未选中)。
*/
function resolveRovingIndex(
key: string,
currentIndex: number,
length: number,
): number | null {
if (length <= 0) {
return null;
}
switch (key) {
case 'Home':
return 0;
case 'End':
return length - 1;
case 'ArrowLeft':
return (currentIndex - 1 + length) % length;
case 'ArrowRight':
return (currentIndex + 1) % length;
default:
return null;
}
}
type PlatformProfileRechargeTab = 'subscription' | 'recharge';
export type PlatformProfileRechargeNativePaymentState = {
@@ -511,20 +537,16 @@ function PlatformRechargeTabNav({
aria-label="会员与泥点"
className="platform-subpanel flex gap-1 rounded-full p-1"
onKeyDown={(event) => {
if (!['ArrowLeft', 'ArrowRight', 'Home', 'End'].includes(event.key)) {
const currentIndex = tabs.findIndex((tab) => tab.id === activeTab);
const nextIndex = resolveRovingIndex(
event.key,
currentIndex,
tabs.length,
);
if (nextIndex === null) {
return;
}
event.preventDefault();
const currentIndex = tabs.findIndex((tab) => tab.id === activeTab);
const nextIndex =
event.key === 'Home'
? 0
: event.key === 'End'
? tabs.length - 1
: (currentIndex +
(event.key === 'ArrowRight' ? 1 : -1) +
tabs.length) %
tabs.length;
const nextTab = tabs[nextIndex];
if (nextTab) {
onChange(nextTab.id);
@@ -851,22 +873,18 @@ function PlatformPointProductGrid({
aria-label="泥点充值档位"
className="grid grid-cols-2 gap-2 sm:grid-cols-3"
onKeyDown={(event) => {
if (!['ArrowLeft', 'ArrowRight', 'Home', 'End'].includes(event.key)) {
return;
}
event.preventDefault();
const currentIndex = products.findIndex(
(product) => product.productId === selectedProductId,
);
const nextIndex =
event.key === 'Home'
? 0
: event.key === 'End'
? products.length - 1
: (currentIndex +
(event.key === 'ArrowRight' ? 1 : -1) +
products.length) %
products.length;
const nextIndex = resolveRovingIndex(
event.key,
currentIndex,
products.length,
);
if (nextIndex === null) {
return;
}
event.preventDefault();
const nextProduct = products[nextIndex];
if (nextProduct) {
onSelect(nextProduct);