产品体验修复:P0 阻塞 + P1/P2 改善(产品审查 14 项中修复 10 项)
P0 阻塞: - Pro 加载不再阻塞整个看板:只显示精简顶栏 + 加载状态,不再遮盖整个页面 - Scan 失败加重试按钮:所有用户(含免费)均可手动重试 - Detail Panel 同步超时后显示提示:"同步时间较长,当前展示的数据可能不完整" P1 体验: - 登录页增加"忘记密码"链接:调用 Supabase 密码重置流程 - 登录失败/邮箱未验证增加明确提示:"如刚注册,请先点击验证链接" - 公告横幅增加 ✕ 关闭按钮:点击后永久隐藏 P2 改善: - entitlement-required 页面重设计:品牌化、增加返回首页和登录按钮 - 订阅帮助页中英双语:所有 FAQ 和 UI 文案支持中英文切换 - 新增产品审查文档 docs/product-review-jun-2026.md Tested: npx tsc --noEmit
This commit is contained in:
@@ -353,12 +353,25 @@ function ScanTerminalScreen() {
|
||||
<div className={scanTerminalRootClassName}>
|
||||
<div className={clsx("scan-terminal", themeMode === "light" && "light")}>
|
||||
<main className="scan-data-grid">
|
||||
<div className="scan-topbar">
|
||||
<div className="scan-topbar-title">
|
||||
<strong>{isEn ? "AI Weather Decision Terminal" : "AI 天气交易决策台"}</strong>
|
||||
<span>
|
||||
{isEn
|
||||
? "Start from the map, then open city cards to verify weather evidence"
|
||||
: "从地图选城市,再打开决策卡验证天气证据"}
|
||||
</span>
|
||||
</div>
|
||||
<div className="scan-topbar-actions">
|
||||
<span className="scan-topbar-time">{userLocalTime}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="scan-loading-state">
|
||||
<LoadingSignal
|
||||
title={isEn ? "Preparing decision workspace" : "正在准备决策工作台"}
|
||||
description={
|
||||
isEn
|
||||
? "Checking access, city context and today’s tradable weather windows."
|
||||
? "Checking access, city context and today's tradable weather windows."
|
||||
: "正在检查权限、城市上下文和今日可交易天气窗口。"
|
||||
}
|
||||
/>
|
||||
@@ -461,6 +474,17 @@ function ScanTerminalScreen() {
|
||||
<li>{isEn ? "HKO observatory AI read" : "香港天文台观测 AI 解读"}</li>
|
||||
<li>{isEn ? "Smoother scrolling experience" : "滚动体验优化"}</li>
|
||||
</ul>
|
||||
<button
|
||||
type="button"
|
||||
className="scan-announcement-dismiss"
|
||||
aria-label={isEn ? "Dismiss" : "关闭"}
|
||||
onClick={() => {
|
||||
localStorage.setItem("polyweather_v156_announcement_seen_at", String(Date.now() + 90 * 24 * 60 * 60 * 1000));
|
||||
setShowAnnouncement(false);
|
||||
}}
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
</section>
|
||||
) : null}
|
||||
|
||||
@@ -534,6 +558,14 @@ function ScanTerminalScreen() {
|
||||
{isEn ? "Scan failed" : "扫描失败"}
|
||||
</div>
|
||||
<div className="scan-empty-copy">{staleReason}</div>
|
||||
<button
|
||||
type="button"
|
||||
className="scan-retry-button"
|
||||
onClick={() => refreshScanTerminalManually()}
|
||||
>
|
||||
<RefreshCw size={13} />
|
||||
{isEn ? "Retry" : "重试"}
|
||||
</button>
|
||||
</div>
|
||||
) : (
|
||||
renderMainView()
|
||||
|
||||
Reference in New Issue
Block a user