修复推荐页滑动切换回弹

为推荐页滑动提交后的 rail 复位增加无过渡 resetting 状态

补充推荐滑动状态模型测试覆盖 resetting 类名

补齐推荐页交互测试中的小程序运行态 mock
This commit is contained in:
kdletters
2026-06-13 20:01:02 +08:00
parent 5a1c1c88dd
commit bdf99468e7
4 changed files with 25 additions and 0 deletions

View File

@@ -200,6 +200,7 @@ const authServiceMocks = vi.hoisted(() => ({
token: 'runtime-guest-token', token: 'runtime-guest-token',
expiresAt: '2099-01-01T00:00:00.000Z', expiresAt: '2099-01-01T00:00:00.000Z',
})), })),
isWechatMiniProgramWebViewRuntime: vi.fn(() => false),
getPublicAuthUserByCode: vi.fn( getPublicAuthUserByCode: vi.fn(
async (publicUserCode: string): Promise<PublicUserSummary> => ({ async (publicUserCode: string): Promise<PublicUserSummary> => ({
id: `public-user-${publicUserCode}`, id: `public-user-${publicUserCode}`,
@@ -222,6 +223,8 @@ const authServiceMocks = vi.hoisted(() => ({
vi.mock('../../services/authService', () => ({ vi.mock('../../services/authService', () => ({
ensureRuntimeGuestToken: authServiceMocks.ensureRuntimeGuestToken, ensureRuntimeGuestToken: authServiceMocks.ensureRuntimeGuestToken,
isWechatMiniProgramWebViewRuntime:
authServiceMocks.isWechatMiniProgramWebViewRuntime,
getPublicAuthUserByCode: authServiceMocks.getPublicAuthUserByCode, getPublicAuthUserByCode: authServiceMocks.getPublicAuthUserByCode,
getPublicAuthUserById: authServiceMocks.getPublicAuthUserById, getPublicAuthUserById: authServiceMocks.getPublicAuthUserById,
})); }));

View File

@@ -3421,6 +3421,8 @@ export function RpgEntryHomeView({
const [recommendDragOffsetY, setRecommendDragOffsetY] = useState(0); const [recommendDragOffsetY, setRecommendDragOffsetY] = useState(0);
const [recommendDragCommitDirection, setRecommendDragCommitDirection] = const [recommendDragCommitDirection, setRecommendDragCommitDirection] =
useState<RecommendSwipeDirection | null>(null); useState<RecommendSwipeDirection | null>(null);
const [isRecommendDragResetting, setIsRecommendDragResetting] =
useState(false);
const activeRecommendEntryKeyForSelection = const activeRecommendEntryKeyForSelection =
recommendFeedWindow.activeEntryKey; recommendFeedWindow.activeEntryKey;
const recommendCardStageRef = useRef<HTMLDivElement | null>(null); const recommendCardStageRef = useRef<HTMLDivElement | null>(null);
@@ -3435,6 +3437,7 @@ export function RpgEntryHomeView({
return; return;
} }
setIsRecommendDragResetting(false);
setRecommendDragCommitDirection(direction); setRecommendDragCommitDirection(direction);
const panelHeight = const panelHeight =
recommendCardStageRef.current?.getBoundingClientRect().height ?? 0; recommendCardStageRef.current?.getBoundingClientRect().height ?? 0;
@@ -3451,8 +3454,12 @@ export function RpgEntryHomeView({
} else { } else {
onSelectPreviousRecommendEntry?.(activeRecommendEntryKeyForSelection); onSelectPreviousRecommendEntry?.(activeRecommendEntryKeyForSelection);
} }
setIsRecommendDragResetting(true);
setRecommendDragOffsetY(0); setRecommendDragOffsetY(0);
setRecommendDragCommitDirection(null); setRecommendDragCommitDirection(null);
window.requestAnimationFrame(() => {
setIsRecommendDragResetting(false);
});
}, RECOMMEND_ENTRY_COMMIT_ANIMATION_MS); }, RECOMMEND_ENTRY_COMMIT_ANIMATION_MS);
}, },
[ [
@@ -3514,6 +3521,7 @@ export function RpgEntryHomeView({
const deltaY = event.clientY - drag.startY; const deltaY = event.clientY - drag.startY;
const commitDirection = resolveRecommendDragCommitDirection(deltaY); const commitDirection = resolveRecommendDragCommitDirection(deltaY);
if (!commitDirection) { if (!commitDirection) {
setIsRecommendDragResetting(false);
setRecommendDragOffsetY(0); setRecommendDragOffsetY(0);
return; return;
} }
@@ -3529,6 +3537,7 @@ export function RpgEntryHomeView({
event.currentTarget.releasePointerCapture?.(drag.pointerId); event.currentTarget.releasePointerCapture?.(drag.pointerId);
} }
recommendDragStartRef.current = null; recommendDragStartRef.current = null;
setIsRecommendDragResetting(false);
setRecommendDragOffsetY(0); setRecommendDragOffsetY(0);
}, },
[], [],
@@ -3539,6 +3548,7 @@ export function RpgEntryHomeView({
const recommendRailClassName = buildRecommendSwipeRailClassName({ const recommendRailClassName = buildRecommendSwipeRailClassName({
offsetY: recommendDragOffsetY, offsetY: recommendDragOffsetY,
commitDirection: recommendDragCommitDirection, commitDirection: recommendDragCommitDirection,
isResetting: isRecommendDragResetting,
}); });
const selectNextRecommendEntry = useCallback(() => { const selectNextRecommendEntry = useCallback(() => {
if ( if (

View File

@@ -38,6 +38,13 @@ describe('rpgEntryRecommendSwipeDeckModel', () => {
expect( expect(
buildRecommendSwipeRailClassName({ offsetY: -320, commitDirection: 1 }), buildRecommendSwipeRailClassName({ offsetY: -320, commitDirection: 1 }),
).toBe('platform-recommend-swipe-rail--committing'); ).toBe('platform-recommend-swipe-rail--committing');
expect(
buildRecommendSwipeRailClassName({
offsetY: 0,
commitDirection: null,
isResetting: true,
}),
).toBe('platform-recommend-swipe-rail--resetting');
expect( expect(
shouldAnimateRecommendSwipe({ shouldAnimateRecommendSwipe({

View File

@@ -9,6 +9,7 @@ export type RecommendSwipeDirection = 1 | -1;
export type RecommendSwipeRailState = { export type RecommendSwipeRailState = {
offsetY: number; offsetY: number;
commitDirection: RecommendSwipeDirection | null; commitDirection: RecommendSwipeDirection | null;
isResetting?: boolean;
}; };
/** 收口推荐卡纵向滑动的纯判定,页面只保留 pointer 与动画副作用。 */ /** 收口推荐卡纵向滑动的纯判定,页面只保留 pointer 与动画副作用。 */
@@ -47,6 +48,10 @@ export function resolveRecommendCommitOffset(
export function buildRecommendSwipeRailClassName( export function buildRecommendSwipeRailClassName(
state: RecommendSwipeRailState, state: RecommendSwipeRailState,
) { ) {
if (state.isResetting) {
return 'platform-recommend-swipe-rail--resetting';
}
if (state.commitDirection) { if (state.commitDirection) {
return 'platform-recommend-swipe-rail--committing'; return 'platform-recommend-swipe-rail--committing';
} }