feat(web): landing 移除顶部下载按钮与 Web 新版本提示; 活性检查改用 /healthz
Docker Build and Push / build-image (push) Waiting to run
Android Build & Publish / build-android (push) Has been cancelled

- 顶部英雄区下载按钮与下方下载区块重复, 删除该按钮; 保留下载区块(按钮+二维码)
- Web 端访问的页面即部署版本, 不应有版本不一致提示: 移除 Landing 的 WebUpdateBanner
- index.html 响应加 Cache-Control: no-cache, no-store 兜底: 避免浏览器/代理缓存旧
  index 导致刷新后仍加载旧哈希资源, 与部署 dist 不一致
- 新增 GET /healthz 作为容器活性检查路径, Dockerfile HEALTHCHECK 从 /api/health 切换
This commit is contained in:
jif2.zhang
2026-09-15 09:25:54 +08:00
parent 65b7fbcd13
commit 7ef8fa43ea
4 changed files with 9 additions and 43 deletions
+1 -40
View File
@@ -1,7 +1,6 @@
import React, { useEffect, useState } from "react";
import React from "react";
import { QRCodeSVG } from "qrcode.react";
import { APP_VERSION, BUILD_ID } from "../version";
import { checkOtaUpdate, reloadApp } from "../api/ota";
// R2 公共桶中的 APK 产物 (由 android-build.yml 上传, 固定覆盖式)
const APK_URL = "https://pub-98ee77ce79984c2cad0dc1c300901158.r2.dev/data/android/wardrobe.apk";
@@ -47,36 +46,6 @@ function DownloadSection() {
);
}
function WebUpdateBanner() {
const [update, setUpdate] = useState(false);
const [note, setNote] = useState("");
useEffect(() => {
checkOtaUpdate().then((r) => {
if (r.available && r.info) {
setUpdate(true);
setNote(r.info.notes || "");
}
});
}, []);
if (!update) return null;
return (
<div style={{ position: "fixed", bottom: 24, left: 0, right: 0, display: "flex", justifyContent: "center", zIndex: 50, padding: "0 16px" }}>
<div style={{ background: "#fff", border: "1px solid var(--border)", borderRadius: "var(--radius)", boxShadow: "0 8px 30px rgba(0,0,0,.12)", padding: "12px 16px", display: "flex", alignItems: "center", gap: 12, maxWidth: 520, width: "100%" }}>
<span style={{ fontSize: 18 }}>🆕</span>
<div style={{ flex: 1, fontSize: 13 }}>
<p style={{ fontWeight: 600 }}>有新版本可用{note ? `: ${note}` : ""}</p>
<p style={{ color: "var(--text-secondary)", fontSize: 12 }}>请刷新页面获取最新体验</p>
</div>
<button className="btn btn-primary" style={{ padding: "8px 16px", fontSize: 13 }} onClick={reloadApp}>
刷新
</button>
</div>
</div>
);
}
export default function Landing() {
return (
<div style={{ minHeight: "100vh", background: "var(--bg)", color: "var(--text-primary)", userSelect: "text" }}>
@@ -98,11 +67,6 @@ export default function Landing() {
Wardrobe 是一款离线优先的衣物管理应用。记录每一件衣物, 智能生成搭配建议,
用数据了解自己的穿搭风格。数据 100% 存在本地, 隐私无忧。
</p>
<div style={{ display: "flex", gap: 12, justifyContent: "center", flexWrap: "wrap", marginTop: 28 }}>
<a className="btn btn-primary" href={APK_URL} download="wardrobe.apk" style={styles.heroBtn}>
⬇️ 下载 Android APK
</a>
</div>
</section>
<DownloadSection />
@@ -146,8 +110,6 @@ export default function Landing() {
<footer style={styles.footer}>
<p>Wardrobe · 构建 {BUILD_ID} · 数据保存在本地设备, 我们看不到你的衣橱</p>
</footer>
<WebUpdateBanner />
</div>
);
}
@@ -166,7 +128,6 @@ const styles: Record<string, React.CSSProperties> = {
hero: { textAlign: "center", padding: "64px 0 48px" },
heroTitle: { fontSize: 40, fontWeight: 800, lineHeight: 1.3, letterSpacing: -0.5 },
heroSub: { fontSize: 16, color: "var(--text-secondary)", lineHeight: 1.8, maxWidth: 560, margin: "18px auto 0" },
heroBtn: { display: "inline-block", width: "auto", padding: "12px 24px", fontSize: 15 },
section: { padding: "40px 0 12px" },
sectionTitle: { fontSize: 24, fontWeight: 700, textAlign: "center" },
sectionSub: { fontSize: 14, color: "var(--text-secondary)", textAlign: "center", margin: "8px 0 22px" },