All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
原因:父容器一直挂着 landscape:overflow-hidden,意图是手机横屏全屏 体验。但 Tailwind 的 landscape: 是纯方向匹配(含桌面横屏显示器), 所以桌面也命中 overflow:hidden,sticky 完全失效,滚动时头部 tab 全部消失,看起来像「半截被遮挡」。 修复:把 landscape: 修饰符改为 max-md:landscape: ,仅在移动端 (< 768px)+ 横屏时生效。桌面恢复正常 overflow:visible,sticky 头部能稳稳停在顶部。 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
87 lines
4.2 KiB
TypeScript
87 lines
4.2 KiB
TypeScript
import { useState } from 'react';
|
||
import { Fuel, BatteryCharging, Receipt, LayoutDashboard, CalendarDays } from 'lucide-react';
|
||
import { motion } from 'motion/react';
|
||
import HydrogenView, { type HydrogenSubTab } from './HydrogenView';
|
||
import ElectricView, { type ElectricSubTab } from './ElectricView';
|
||
import ETCView from './ETCView';
|
||
|
||
type TopTab = 'hydrogen' | 'electric' | 'etc';
|
||
type SubTabId = HydrogenSubTab | ElectricSubTab; // 'daily' | 'overview'
|
||
|
||
const TABS: { key: TopTab; label: string; icon: typeof Fuel }[] = [
|
||
{ key: 'hydrogen', label: '氢能', icon: Fuel },
|
||
{ key: 'electric', label: '电能', icon: BatteryCharging },
|
||
{ key: 'etc', label: 'ETC', icon: Receipt },
|
||
];
|
||
|
||
const SUB_TABS: { id: SubTabId; label: string; icon: typeof LayoutDashboard }[] = [
|
||
{ id: 'daily', label: '每日', icon: CalendarDays },
|
||
{ id: 'overview', label: '总览', icon: LayoutDashboard },
|
||
];
|
||
|
||
export default function EnergyModule() {
|
||
const [activeTab, setActiveTab] = useState<TopTab>('hydrogen');
|
||
const [hydroSub, setHydroSub] = useState<HydrogenSubTab>('daily');
|
||
const [electricSub, setElectricSub] = useState<ElectricSubTab>('daily');
|
||
const showSubTabs = activeTab === 'hydrogen' || activeTab === 'electric';
|
||
const currentSub: SubTabId = activeTab === 'electric' ? electricSub : hydroSub;
|
||
const setSub = (id: SubTabId) => activeTab === 'electric' ? setElectricSub(id) : setHydroSub(id);
|
||
return (
|
||
<div className="min-h-screen bg-[#F8F9FB] text-gray-800 font-sans p-3 md:p-6 relative" style={{ overflowX: 'clip' }}>
|
||
<div className="max-w-6xl mx-auto flex flex-col gap-3 pb-16 max-md:landscape:pb-0 max-md:landscape:h-full max-md:landscape:flex-1 max-md:landscape:overflow-hidden">
|
||
|
||
{/* 统一 sticky 头部:top tab + (氢能时) 子 tab;同一张卡片,无间隙 */}
|
||
{/* pb-4 留一点底部缓冲,避免下方快捷选按钮在滚动时贴着 sticky 半截露脸 */}
|
||
<div className="sticky top-0 z-30 -mx-3 md:-mx-6 px-3 md:px-6 -mt-3 md:-mt-6 pt-3 md:pt-6 pb-4 bg-[#F8F9FB] shadow-[0_8px_12px_-12px_rgba(15,23,42,0.08)]">
|
||
<div className="bg-white rounded-2xl border border-slate-100 shadow-sm overflow-hidden">
|
||
{/* 顶部 tab:氢能 / 电能 / ETC */}
|
||
<div className={`px-4 py-2 flex items-center gap-6 ${showSubTabs ? 'border-b border-slate-50' : ''}`}>
|
||
{TABS.map(tab => {
|
||
const Icon = tab.icon;
|
||
const active = activeTab === tab.key;
|
||
return (
|
||
<button
|
||
key={tab.key}
|
||
onClick={() => setActiveTab(tab.key)}
|
||
className={`flex items-center gap-2 py-1 transition-colors relative ${active ? 'text-blue-600' : 'text-slate-400 hover:text-slate-600'}`}
|
||
>
|
||
<Icon size={14} />
|
||
<span className="text-[11px] font-bold">{tab.label}</span>
|
||
{active && (
|
||
<motion.div layoutId="activeEnergyTopTab" className="absolute -bottom-2 left-0 right-0 h-0.5 bg-blue-600 rounded-full" />
|
||
)}
|
||
</button>
|
||
);
|
||
})}
|
||
</div>
|
||
{/* 子 tab:氢能 / 电能 都显示 每日 / 总览 */}
|
||
{showSubTabs && (
|
||
<div className="p-1 flex gap-1">
|
||
{SUB_TABS.map(({ id, label, icon: Icon }) => {
|
||
const active = currentSub === id;
|
||
return (
|
||
<button
|
||
key={id}
|
||
onClick={() => setSub(id)}
|
||
className={`flex-1 flex items-center justify-center gap-1.5 rounded-xl py-1.5 text-[12px] font-bold transition-all ${
|
||
active ? 'bg-blue-50 text-blue-600' : 'text-slate-400 hover:bg-slate-50'
|
||
}`}
|
||
>
|
||
<Icon size={14} />
|
||
<span>{label}</span>
|
||
</button>
|
||
);
|
||
})}
|
||
</div>
|
||
)}
|
||
</div>
|
||
</div>
|
||
|
||
{activeTab === 'hydrogen' && <HydrogenView sub={hydroSub} />}
|
||
{activeTab === 'electric' && <ElectricView sub={electricSub} />}
|
||
{activeTab === 'etc' && <ETCView />}
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|