Skip to content

Commit 4dd9a9b

Browse files
committed
a
1 parent 883c825 commit 4dd9a9b

1 file changed

Lines changed: 94 additions & 1 deletion

File tree

index.html

Lines changed: 94 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,4 +54,97 @@
5454
border-radius: var(--radius);
5555
overflow:hidden;
5656
box-shadow: 0 6px 18px rgba(0,0,0,.08);
57-
transition: tr
57+
transition: transform .18s ease, box-shadow .18s ease;
58+
}
59+
@media (hover:hover){
60+
.card:hover{
61+
transform: translateY(-2px);
62+
box-shadow: 0 10px 28px rgba(0,0,0,.12);
63+
}
64+
}
65+
66+
.player{ position:relative; aspect-ratio:16/9; background:#000; }
67+
video, img{ width:100%; height:100%; object-fit:cover; display:block; border:0; }
68+
</style>
69+
</head>
70+
<body>
71+
72+
<!-- 新增的大标题 -->
73+
<header>
74+
<div class="wrap">
75+
<h1>Expert Policy</h1>
76+
</div>
77+
</header>
78+
79+
<main class="grid" id="grid"></main>
80+
81+
<script>
82+
async function loadManifest(){
83+
const res = await fetch('manifest.json', { cache: 'no-store' });
84+
if(!res.ok) throw new Error('manifest.json 加载失败');
85+
return res.json();
86+
}
87+
88+
/* 洗牌:Fisher–Yates */
89+
function shuffle(arr){
90+
for(let i = arr.length - 1; i > 0; i--){
91+
const j = Math.floor(Math.random() * (i + 1));
92+
[arr[i], arr[j]] = [arr[j], arr[i]];
93+
}
94+
return arr;
95+
}
96+
97+
function makeCard(item){
98+
const card = document.createElement('article');
99+
card.className = 'card';
100+
101+
const player = document.createElement('div');
102+
player.className = 'player';
103+
104+
// 先放海报,进入视口再换成 <video>
105+
const poster = document.createElement('img');
106+
poster.alt = item.title || item.file || '';
107+
poster.loading = 'lazy';
108+
poster.decoding = 'async';
109+
poster.src = item.poster || '';
110+
if(!item.poster){ poster.style.background = '#000'; }
111+
player.appendChild(poster);
112+
113+
card.appendChild(player);
114+
115+
// 懒加载:出现时才创建 <video>
116+
const io = new IntersectionObserver(entries => {
117+
for(const e of entries){
118+
if(e.isIntersecting){
119+
io.disconnect();
120+
const v = document.createElement('video');
121+
v.setAttribute('controls', '');
122+
v.setAttribute('playsinline','');
123+
v.setAttribute('preload','metadata');
124+
if(item.poster) v.setAttribute('poster', item.poster);
125+
v.src = item.src; // 相对路径,如 videos/xxx.mp4
126+
player.replaceChild(v, poster);
127+
}
128+
}
129+
}, { rootMargin: '160px' });
130+
io.observe(card);
131+
132+
return card;
133+
}
134+
135+
function render(list){
136+
const grid = document.getElementById('grid');
137+
grid.innerHTML = '';
138+
for(const item of list){ grid.appendChild(makeCard(item)); }
139+
}
140+
141+
/* 加载清单 → 打乱 → 渲染一次 */
142+
loadManifest()
143+
.then(list => { render(shuffle(list.slice())); })
144+
.catch(err => {
145+
const grid = document.getElementById('grid');
146+
grid.innerHTML = `<p style="opacity:.8;padding:16px">加载清单失败:${err.message}。请确认 manifest.json 已生成并在仓库根目录。</p>`;
147+
});
148+
</script>
149+
</body>
150+
</html>

0 commit comments

Comments
 (0)