VideoCard操作菜单限制高度并可滑动:有源最多4项、无源最多6项

This commit is contained in:
mtvpls
2026-07-26 15:29:03 +08:00
parent 333c482e19
commit c4be0e1886
+46 -1
View File
@@ -51,6 +51,13 @@ const MobileActionSheet: React.FC<MobileActionSheetProps> = ({
const [isTitleOverflowing, setIsTitleOverflowing] = useState(false); const [isTitleOverflowing, setIsTitleOverflowing] = useState(false);
const backdropPressStarted = useRef(false); const backdropPressStarted = useRef(false);
const titleRef = useRef<HTMLHeadingElement>(null); const titleRef = useRef<HTMLHeadingElement>(null);
const actionsListRef = useRef<HTMLDivElement>(null);
// 操作区可滚动:有可用播放源最多显示 4 项,否则最多 6 项
const hasPlaySources = Boolean(isAggregate && sources && sources.length > 0);
// 单项 py-4(2rem) + 内容 h-6(1.5rem) = 3.5rem
const actionsMaxVisible = hasPlaySources ? 4 : 6;
const actionsMaxHeight = `calc(3.5rem * ${actionsMaxVisible})`;
// 确保组件在客户端挂载后才渲染 Portal // 确保组件在客户端挂载后才渲染 Portal
useEffect(() => { useEffect(() => {
@@ -166,6 +173,31 @@ const MobileActionSheet: React.FC<MobileActionSheetProps> = ({
}; };
}, [isVisible, title]); }, [isVisible, title]);
// 操作列表:用非 passive 的 wheel 监听,保证鼠标滚轮可滚动且不穿透到背景
useEffect(() => {
if (!isVisible) return;
const el = actionsListRef.current;
if (!el) return;
const handleWheel = (e: WheelEvent) => {
e.stopPropagation();
const { scrollTop, scrollHeight, clientHeight } = el;
if (scrollHeight <= clientHeight) {
e.preventDefault();
return;
}
const maxScrollTop = scrollHeight - clientHeight;
const next = Math.min(maxScrollTop, Math.max(0, scrollTop + e.deltaY));
if (next !== scrollTop) {
el.scrollTop = next;
}
e.preventDefault();
};
el.addEventListener('wheel', handleWheel, { passive: false });
return () => el.removeEventListener('wheel', handleWheel);
}, [isVisible, actionsMaxVisible]);
// ESC键关闭 // ESC键关闭
useEffect(() => { useEffect(() => {
const handleEsc = (e: KeyboardEvent) => { const handleEsc = (e: KeyboardEvent) => {
@@ -337,8 +369,20 @@ const MobileActionSheet: React.FC<MobileActionSheetProps> = ({
</button> </button>
</div> </div>
{/* 操作列表 */} {/* 操作列表:有源最多 4 项 / 无源最多 6 项,超出可滑动(支持触控与鼠标滚轮) */}
<div className="px-4 py-2"> <div className="px-4 py-2">
<div
ref={actionsListRef}
className="overflow-y-auto overscroll-contain"
style={{
maxHeight: actionsMaxHeight,
WebkitOverflowScrolling: 'touch',
}}
onTouchMove={(e) => {
// 允许操作列表内部滑动,阻止冒泡到外层遮罩
e.stopPropagation();
}}
>
{actions.map((action, index) => ( {actions.map((action, index) => (
<div key={action.id}> <div key={action.id}>
<button <button
@@ -394,6 +438,7 @@ const MobileActionSheet: React.FC<MobileActionSheetProps> = ({
</div> </div>
))} ))}
</div> </div>
</div>
{/* 播放源信息展示区域 */} {/* 播放源信息展示区域 */}
{isAggregate && sources && sources.length > 0 && ( {isAggregate && sources && sources.length > 0 && (