Skip to content

Commit 80cd41f

Browse files
committed
优化瀑布流显示
1 parent 5159d82 commit 80cd41f

File tree

1 file changed

+78
-9
lines changed

1 file changed

+78
-9
lines changed

backend/app/api/public/wtf_page.py

Lines changed: 78 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,13 @@ def u(path: str) -> str:
6464
a:hover {{ text-decoration: underline; }}
6565
6666
.wrap {{
67-
max-width: 980px;
67+
max-width: 1180px;
6868
margin: 0 auto;
6969
padding: 22px 16px 44px;
7070
}}
71+
@media (min-width: 1400px) {{
72+
.wrap {{ max-width: 1280px; }}
73+
}}
7174
@media (max-width: 520px) {{
7275
.wrap {{ padding: 18px 12px 40px; }}
7376
}}
@@ -151,6 +154,25 @@ def u(path: str) -> str:
151154
content-visibility: auto;
152155
contain-intrinsic-size: 800px;
153156
}}
157+
@keyframes shimmer {{
158+
0% {{ background-position: 0% 0; }}
159+
100% {{ background-position: 200% 0; }}
160+
}}
161+
.item.pending {{
162+
background: linear-gradient(
163+
90deg,
164+
rgba(255, 250, 243, 0.86),
165+
rgba(255, 250, 243, 0.56),
166+
rgba(255, 250, 243, 0.86)
167+
);
168+
background-size: 200% 100%;
169+
animation: shimmer 1100ms ease-in-out infinite;
170+
border-color: rgba(58, 38, 26, 0.10);
171+
box-shadow: none;
172+
}}
173+
.item.pending img {{
174+
aspect-ratio: var(--ar, 16 / 9);
175+
}}
154176
.item img {{
155177
width: 100%;
156178
height: auto;
@@ -165,9 +187,9 @@ def u(path: str) -> str:
165187
}}
166188
.sentinel {{
167189
text-align: center;
168-
padding: 18px 0 0;
190+
padding: 12px 0 0;
169191
color: var(--muted2);
170-
font-size: 12px;
192+
font-size: 11px;
171193
}}
172194
</style>
173195
</head>
@@ -214,6 +236,7 @@ def u(path: str) -> str:
214236
let inflight = 0;
215237
let rendered = 0;
216238
let target = 0;
239+
let failStreak = 0;
217240
218241
function isMobile() {{
219242
return window.matchMedia && window.matchMedia("(max-width: 520px)").matches;
@@ -226,16 +249,29 @@ def u(path: str) -> str:
226249
const slow = effectiveType.includes("2g") || effectiveType.includes("3g");
227250
228251
const base = mobile
229-
? {{ initial: 8, step: 6, maxInflight: 8 }}
230-
: {{ initial: 12, step: 10, maxInflight: 14 }};
252+
? {{ initial: 12, step: 8, maxInflight: 12 }}
253+
: {{ initial: 18, step: 14, maxInflight: 22 }};
231254
232255
return {{
233256
initial: base.initial,
234257
step: base.step,
235-
maxInflight: slow ? Math.max(4, Math.floor(base.maxInflight / 2)) : base.maxInflight,
258+
maxInflight: slow ? Math.max(6, Math.floor(base.maxInflight * 0.6)) : base.maxInflight,
236259
}};
237260
}}
238261
262+
function pickSkeletonRatio() {{
263+
const o = String(baseParams.get("orientation") || "").trim().toLowerCase();
264+
if (o === "square") return "1 / 1";
265+
if (o === "portrait") return "2 / 3";
266+
if (o === "landscape") return "16 / 9";
267+
268+
const adaptiveRaw = String(baseParams.get("adaptive") || "").trim().toLowerCase();
269+
const adaptiveOn = baseParams.has("adaptive") && adaptiveRaw !== "0" && adaptiveRaw !== "false";
270+
if (adaptiveOn) return isMobile() ? "2 / 3" : "16 / 9";
271+
272+
return isMobile() ? "3 / 4" : "16 / 9";
273+
}}
274+
239275
function buildUrl() {{
240276
const p = new URLSearchParams(baseParams);
241277
p.set("t", String(Date.now()) + "_" + String(seq++));
@@ -264,10 +300,16 @@ def u(path: str) -> str:
264300
inflight += 1;
265301
updateSentinel();
266302
303+
const item = document.createElement("div");
304+
item.className = "item pending";
305+
item.style.setProperty("--ar", pickSkeletonRatio());
306+
267307
const img = new Image();
268308
img.decoding = "async";
269309
img.referrerPolicy = "no-referrer";
270310
img.alt = "";
311+
item.appendChild(img);
312+
feed.appendChild(item);
271313
272314
let tries = 0;
273315
const load = () => {{
@@ -278,7 +320,9 @@ def u(path: str) -> str:
278320
img.onload = () => {{
279321
inflight = Math.max(0, inflight - 1);
280322
rendered += 1;
281-
appendItem(img);
323+
failStreak = 0;
324+
item.classList.remove("pending");
325+
requestAnimationFrame(() => item.classList.add("loaded"));
282326
updateSentinel();
283327
ensure();
284328
}};
@@ -288,7 +332,15 @@ def u(path: str) -> str:
288332
return;
289333
}}
290334
inflight = Math.max(0, inflight - 1);
335+
failStreak += 1;
336+
try {{ item.remove(); }} catch (e) {{}}
291337
updateSentinel();
338+
if (failStreak >= 8) {{
339+
paused = true;
340+
toggle.textContent = "继续加载";
341+
sentinel.textContent = "连续失败较多:可能网络不稳定或当前过滤无匹配,请放宽条件后重试。";
342+
return;
343+
}}
292344
ensure();
293345
}};
294346
@@ -305,7 +357,12 @@ def u(path: str) -> str:
305357
306358
function bump() {{
307359
const c = cfg();
308-
target = Math.max(target, rendered + inflight + c.step);
360+
const dist = Math.max(0, document.documentElement.scrollHeight - (window.scrollY + window.innerHeight));
361+
let m = 1;
362+
if (dist < window.innerHeight * 0.8) m = 4;
363+
else if (dist < window.innerHeight * 1.6) m = 3;
364+
else if (dist < window.innerHeight * 2.6) m = 2;
365+
target = Math.max(target, rendered + inflight + c.step * m);
309366
ensure();
310367
}}
311368
@@ -322,9 +379,21 @@ def u(path: str) -> str:
322379
for (const e of entries) {{
323380
if (e.isIntersecting) bump();
324381
}}
325-
}}, {{ root: null, rootMargin: "2200px 0px", threshold: 0 }});
382+
}}, {{ root: null, rootMargin: "5200px 0px", threshold: 0 }});
326383
io.observe(sentinel);
327384
385+
let scrollTick = 0;
386+
window.addEventListener("scroll", () => {{
387+
if (paused) return;
388+
if (scrollTick) return;
389+
scrollTick = 1;
390+
requestAnimationFrame(() => {{
391+
scrollTick = 0;
392+
const dist = Math.max(0, document.documentElement.scrollHeight - (window.scrollY + window.innerHeight));
393+
if (dist < window.innerHeight * 3.2) bump();
394+
}});
395+
}}, {{ passive: true }});
396+
328397
// Initial fill.
329398
target = cfg().initial;
330399
ensure();

0 commit comments

Comments
 (0)