diff --git a/web/website/src/components/Download.astro b/web/website/src/components/Download.astro index c8fdaf4..aaacdc3 100644 --- a/web/website/src/components/Download.astro +++ b/web/website/src/components/Download.astro @@ -7,11 +7,17 @@ interface Props { t: T } const { t } = Astro.props; // href 缺省 = 未接入下载 → 禁用「敬请期待」占位。 -// iOS/iPad 目前仅「测试版」(TestFlight 公开链接,需美区 Apple ID);「正式版」(App Store)敬请期待。 -const plats: { icon: string; name: string; ver: string; href?: string; badge?: string; note?: string }[] = [ - { icon: 'smartphone', name: 'iOS', ver: 'iOS 15+', href: SITE.downloads.ios, badge: t('dl.beta'), note: t('dl.us_id') }, - { icon: 'tablet', name: 'iPad', ver: 'iPadOS 15+', href: SITE.downloads.ios, badge: t('dl.beta'), note: t('dl.us_id') }, - { icon: 'smartphone', name: 'iOS / iPad', ver: 'App Store', badge: t('dl.stable') }, +// iOS/iPad 合成一张卡、两个按钮:「测试版」(TestFlight 公开链接) 现已可装, +// 「正式版」(App Store) 禁用,按钮内带「?」——悬浮提示「美区即将上线,需美区 Apple ID」。 +type Action = { label: string; href?: string; hint?: string }; +const plats: { icon: string; name: string; ver: string; href?: string; badge?: string; note?: string; actions?: Action[] }[] = [ + { + icon: 'smartphone', name: 'iOS / iPad', ver: 'iOS / iPadOS 15+', + actions: [ + { label: t('dl.beta'), href: SITE.downloads.ios }, + { label: t('dl.stable'), hint: `${t('dl.us_soon')} · ${t('dl.us_id')}` }, + ], + }, { icon: 'smartphone', name: 'Android', ver: 'Android 9+', href: SITE.downloads.android }, { icon: 'laptop', name: 'macOS', ver: 'macOS 12+', href: SITE.downloads.macos }, { icon: 'monitor', name: 'Windows', ver: 'Win 10/11', href: SITE.downloads.windows }, @@ -35,7 +41,24 @@ const plats: { icon: string; name: string; ver: string; href?: string; badge?: s {p.note && ?}
{p.ver}
- {p.href ? ( + {p.actions ? ( +
+ {p.actions.map((a) => ( + a.href ? ( + {a.label} + ) : ( + + {a.label} + {a.hint && ( + + ?{a.hint} + + )} + + ) + ))} +
+ ) : p.href ? ( {t('dl.get')} ) : ( {t('dl.soon')} @@ -56,9 +79,45 @@ const plats: { icon: string; name: string; ver: string; href?: string; badge?: s font-family: var(--font-mono); letter-spacing: .02em; } .dl .q { + position: relative; display: inline-flex; align-items: center; justify-content: center; width: 16px; height: 16px; border-radius: 50%; - font-size: 11px; font-weight: 700; cursor: help; + font-size: 11px; font-weight: 700; cursor: default; background: var(--bg-subtle); color: var(--fg3); } + /* 自定义提示气泡:走设计 token,悬浮/聚焦「?」时上浮显示,带小箭头。 */ + .dl .q .tip { + position: absolute; bottom: calc(100% + 9px); left: 50%; + transform: translateX(-50%) translateY(4px); + width: max-content; max-width: 210px; white-space: normal; + padding: 8px 11px; border-radius: var(--radius-md, 10px); + background: var(--fg1); color: var(--bg); + font-family: var(--font-sans); font-size: 12px; font-weight: 500; + line-height: 1.45; text-align: center; letter-spacing: 0; + box-shadow: var(--shadow-md, 0 6px 20px rgba(45,30,20,.18)); + opacity: 0; visibility: hidden; pointer-events: none; z-index: 20; + transition: opacity var(--dur-base, .18s) var(--ease-out, ease), + transform var(--dur-base, .18s) var(--ease-out, ease), + visibility var(--dur-base, .18s); + } + .dl .q .tip::after { + content: ""; position: absolute; top: 100%; left: 50%; + transform: translateX(-50%); + border: 5px solid transparent; border-top-color: var(--fg1); + } + .dl .q:hover .tip, .dl .q:focus-visible .tip { + opacity: 1; visibility: visible; transform: translateX(-50%) translateY(0); + } + /* iOS/iPad 单卡双按钮:测试版(实心 accent 可点)+ 正式版(描边禁用,内含「?」悬浮提示)。 */ + .dl .btns { display: flex; gap: 8px; justify-content: center; flex-wrap: wrap; margin-top: 2px; } + .dl .b2 { + display: inline-flex; align-items: center; justify-content: center; gap: 6px; + padding: 8px 15px; border-radius: 999px; line-height: 1.15; + font-size: 13px; font-weight: 600; text-decoration: none; + border: 1px solid var(--accent); color: var(--accent); + } + .dl .b2.beta { background: var(--accent); color: var(--fg-on-accent); border-color: var(--accent); } + /* 禁用态:不导航(本就是 span)+ 默认光标,但不禁用指针事件——否则内含「?」的 title 悬浮失效。 */ + .dl .b2.disabled { border-color: var(--border); color: var(--fg3); cursor: default; } + .dl .b2 .q { background: transparent; border: 1px solid var(--border); } diff --git a/web/website/src/i18n/strings.ts b/web/website/src/i18n/strings.ts index bc25a9a..ffb4ba2 100644 --- a/web/website/src/i18n/strings.ts +++ b/web/website/src/i18n/strings.ts @@ -140,6 +140,7 @@ export const STRINGS: Record> = { 'dl.beta': { zh: '测试版', en: 'Beta', ja: 'ベータ版', ko: '베타', ru: 'Бета', es: 'Beta' }, 'dl.stable': { zh: '正式版', en: 'Stable', ja: '正式版', ko: '정식판', ru: 'Релиз', es: 'Estable' }, 'dl.us_id': { zh: '需美区 Apple ID', en: 'Requires a US Apple ID', ja: '米国 Apple ID が必要', ko: '미국 Apple ID 필요', ru: 'Нужен Apple ID (США)', es: 'Requiere un Apple ID de EE. UU.' }, + 'dl.us_soon': { zh: '美区即将上线', en: 'Coming to US App Store', ja: '米国 App Store で近日公開', ko: '미국 App Store 출시 예정', ru: 'Скоро в App Store (США)', es: 'Pronto en App Store (EE. UU.)' }, 'docs.eyebrow': { zh: '文档', en: 'Docs', ja: 'ドキュメント', ko: '문서', ru: 'Документация', es: 'Documentación' }, 'docs.h': { zh: '需要帮助?都在这里', en: 'Need help? It’s all here', ja: 'お困りですか?すべてここに', ko: '도움이 필요하세요? 모두 여기에', ru: 'Нужна помощь? Всё здесь', es: '¿Necesitas ayuda? Todo está aquí' },