Merge remote-tracking branch 'origin/master' into codex/generation-task-reliability

# Conflicts:
#	src/components/AppShell.tsx
This commit is contained in:
2026-06-05 18:38:08 +08:00
4 changed files with 1218 additions and 34 deletions
+1 -1
View File
@@ -101,7 +101,7 @@ function AppShell({
const [navJustActivated, setNavJustActivated] = useState<WebViewKey | null>(null); const [navJustActivated, setNavJustActivated] = useState<WebViewKey | null>(null);
const isAuthView = activeView === "login"; const isAuthView = activeView === "login";
const isImmersiveView = activeView === "agent" || activeView === "avatarConsole"; const isImmersiveView = activeView === "agent" || activeView === "avatarConsole";
const showFloatingNav = (!isAuthView || !!session) && !isImmersiveView && activeView !== "home"; const showFloatingNav = !isAuthView && !isImmersiveView && activeView !== "home";
const showPageScrollActions = showFloatingNav && !TOOL_SURFACE_VIEW_SET.has(activeView); const showPageScrollActions = showFloatingNav && !TOOL_SURFACE_VIEW_SET.has(activeView);
const visibleNavItems = useMemo( const visibleNavItems = useMemo(
+43 -17
View File
@@ -261,6 +261,30 @@ function ProfilePage({
const packageLabel = session?.user.activePackages?.[0]?.name || "按量积分"; const packageLabel = session?.user.activePackages?.[0]?.name || "按量积分";
const avatarUrl = session?.user.avatarUrl || localAvatarUrl || null; const avatarUrl = session?.user.avatarUrl || localAvatarUrl || null;
const displayedBio = profileBio.trim() || "这个人还没有填写个性签名"; const displayedBio = profileBio.trim() || "这个人还没有填写个性签名";
const activePanelTitle =
activePanel === "works"
? "代表作"
: activePanel === "projects"
? "服务器项目"
: activePanel === "assets"
? "我的资产"
: "社区审核";
const activePanelDescription =
activePanel === "works"
? "最近完成的高质量生成内容"
: activePanel === "projects"
? "云端同步的创作项目"
: activePanel === "assets"
? "可复用的图片、视频与素材"
: "已提交社区的案例状态";
const activePanelCount =
activePanel === "works"
? visibleWorks.length
: activePanel === "projects"
? projects.length
: activePanel === "assets"
? savedAssets.length
: communityCases.length;
const emailLooksValid = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email.trim()); const emailLooksValid = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email.trim());
const phoneLooksValid = /^1[3-9]\d{9}$/.test(phone.trim()); const phoneLooksValid = /^1[3-9]\d{9}$/.test(phone.trim());
const passwordLooksReady = password.length >= (mode === "register" ? 6 : 1); const passwordLooksReady = password.length >= (mode === "register" ? 6 : 1);
@@ -766,9 +790,9 @@ function ProfilePage({
className={`profile-page__banner${bannerUrl ? " has-image" : ""}`} className={`profile-page__banner${bannerUrl ? " has-image" : ""}`}
style={bannerUrl ? { backgroundImage: `url(${bannerUrl})` } : undefined} style={bannerUrl ? { backgroundImage: `url(${bannerUrl})` } : undefined}
> >
<button type="button" className="profile-page__banner-btn" onClick={() => bannerInputRef.current?.click()}> <button type="button" className="profile-page__banner-btn" onClick={() => bannerInputRef.current?.click()} aria-label="更换背景">
<CameraOutlined /> <CameraOutlined />
<span className="profile-page__banner-btn-label"></span>
</button> </button>
<div className="profile-page__banner-overlay" /> <div className="profile-page__banner-overlay" />
</header> </header>
@@ -848,14 +872,16 @@ function ProfilePage({
className={accountPanel === "credits" ? "is-active" : ""} className={accountPanel === "credits" ? "is-active" : ""}
onClick={() => setAccountPanel("credits")} onClick={() => setAccountPanel("credits")}
> >
{(totalBalance / 100).toFixed(2)} <span></span>
<strong>{(totalBalance / 100).toFixed(2)}</strong>
</button> </button>
<button <button
type="button" type="button"
className={accountPanel === "tasks" ? "is-active" : ""} className={accountPanel === "tasks" ? "is-active" : ""}
onClick={() => setAccountPanel("tasks")} onClick={() => setAccountPanel("tasks")}
> >
{tasks.length} <span></span>
<strong>{tasks.length}</strong>
</button> </button>
</div> </div>
<div className="profile-page__account-summary"> <div className="profile-page__account-summary">
@@ -864,6 +890,7 @@ function ProfilePage({
<span className="profile-page__account-summary-main"> <span className="profile-page__account-summary-main">
<small></small> <small></small>
<strong>{displayName}</strong> <strong>{displayName}</strong>
<em>{packageLabel}</em>
</span> </span>
<span className="profile-page__account-summary-metric"> <span className="profile-page__account-summary-metric">
<small></small> <small></small>
@@ -875,6 +902,7 @@ function ProfilePage({
<span className="profile-page__account-summary-main"> <span className="profile-page__account-summary-main">
<small></small> <small></small>
<strong>{tasks.length} </strong> <strong>{tasks.length} </strong>
<em>{completedTasks.length} </em>
</span> </span>
<span className="profile-page__account-summary-metric"> <span className="profile-page__account-summary-metric">
<small></small> <small></small>
@@ -885,6 +913,7 @@ function ProfilePage({
</div> </div>
</div> </div>
<div className="profile-page__actions">
<button type="button" className="profile-page__share-btn profile-page__share-btn--plan"> <button type="button" className="profile-page__share-btn profile-page__share-btn--plan">
<ShareAltOutlined /> <ShareAltOutlined />
{packageLabel} {packageLabel}
@@ -902,34 +931,31 @@ function ProfilePage({
<LockOutlined /> <LockOutlined />
退 退
</button> </button>
</div>
</aside> </aside>
<main className="profile-page__main"> <main className="profile-page__main">
<div className="profile-page__main-tabs"> <div className="profile-page__main-tabs">
<button type="button" className={activePanel === "works" ? "is-active" : ""} onClick={() => setActivePanel("works")}> <button type="button" className={activePanel === "works" ? "is-active" : ""} onClick={() => setActivePanel("works")}>
<span></span>
</button> </button>
<button type="button" className={activePanel === "projects" ? "is-active" : ""} onClick={() => setActivePanel("projects")}> <button type="button" className={activePanel === "projects" ? "is-active" : ""} onClick={() => setActivePanel("projects")}>
<span></span>
</button> </button>
<button type="button" className={activePanel === "assets" ? "is-active" : ""} onClick={() => setActivePanel("assets")}> <button type="button" className={activePanel === "assets" ? "is-active" : ""} onClick={() => setActivePanel("assets")}>
<span></span>
</button> </button>
<button type="button" className={activePanel === "community" ? "is-active" : ""} onClick={() => setActivePanel("community")}> <button type="button" className={activePanel === "community" ? "is-active" : ""} onClick={() => setActivePanel("community")}>
<span></span>
</button> </button>
</div> </div>
<div className="profile-page__section"> <div className="profile-page__section">
<span className="profile-page__section-label"> <div className="profile-page__section-head">
{activePanel === "works" <span className="profile-page__section-label">{activePanelTitle}</span>
? "代表作" <span className="profile-page__section-desc">{activePanelDescription}</span>
: activePanel === "projects" <span className="profile-page__section-meta">{activePanelCount} </span>
? "服务器项目" </div>
: activePanel === "assets"
? "我的资产"
: "社区审核"}
</span>
{renderActivePanel()} {renderActivePanel()}
</div> </div>
</main> </main>
+7
View File
@@ -15,3 +15,10 @@
.profile-page__works-scroll .profile-page__list-grid { .profile-page__works-scroll .profile-page__list-grid {
grid-template-columns: repeat(3, 1fr); /* 固定3列,刚好3×3=9个可见 */ grid-template-columns: repeat(3, 1fr); /* 固定3列,刚好3×3=9个可见 */
} }
/* Dashboard uses natural page scrolling instead of a nested works scroller. */
.profile-page--dashboard .profile-page__works-scroll {
max-height: none;
overflow: visible;
scrollbar-width: auto;
}
File diff suppressed because it is too large Load Diff