修复首页账户帮助菜单交互
统一我的和帮助菜单为点击触发 菜单项接入占位通知弹窗并提升弹层层级 调整泥点与升级入口为分段胶囊样式 补充首页菜单交互边界测试
This commit is contained in:
@@ -16,7 +16,6 @@ import {
|
||||
BookOpen,
|
||||
CircleHelp,
|
||||
Contact,
|
||||
CreditCard,
|
||||
FileText,
|
||||
FolderKanban,
|
||||
Gamepad2,
|
||||
@@ -29,8 +28,8 @@ import {
|
||||
Sparkles,
|
||||
Upload,
|
||||
User,
|
||||
Wallet,
|
||||
X,
|
||||
Zap,
|
||||
} from 'lucide-react';
|
||||
|
||||
import type {
|
||||
@@ -2168,6 +2167,11 @@ export function WorkspaceLauncher({
|
||||
const [walletLedgerStatus, setWalletLedgerStatus] =
|
||||
useState('尚未读取明细');
|
||||
const [accountMenuOpen, setAccountMenuOpen] = useState(false);
|
||||
const [helpMenuOpen, setHelpMenuOpen] = useState(false);
|
||||
const [launcherNotice, setLauncherNotice] = useState<{
|
||||
title: string;
|
||||
message: string;
|
||||
} | null>(null);
|
||||
const [showcaseResources, setShowcaseResources] = useState<
|
||||
EditorShowcaseResource[]
|
||||
>([]);
|
||||
@@ -2702,6 +2706,15 @@ export function WorkspaceLauncher({
|
||||
}
|
||||
}
|
||||
|
||||
function showLauncherNotice(title: string) {
|
||||
setAccountMenuOpen(false);
|
||||
setHelpMenuOpen(false);
|
||||
setLauncherNotice({
|
||||
title,
|
||||
message: `${title}正在接入中,当前版本会先保留入口。`,
|
||||
});
|
||||
}
|
||||
|
||||
function handleRecentWorkspaceRefresh() {
|
||||
if (recentWorkspaces.length === 0 || recentWorkspaceRefreshing) {
|
||||
return;
|
||||
@@ -2985,7 +2998,12 @@ export function WorkspaceLauncher({
|
||||
<button
|
||||
type="button"
|
||||
className="launcher-config-button"
|
||||
onClick={() => setAccountMenuOpen((open) => !open)}
|
||||
onClick={() => {
|
||||
setHelpMenuOpen(false);
|
||||
setWalletPanelOpen(false);
|
||||
setAccountMenuOpen((open) => !open);
|
||||
}}
|
||||
aria-expanded={accountMenuOpen}
|
||||
aria-label="我的"
|
||||
title="我的"
|
||||
>
|
||||
@@ -3000,21 +3018,21 @@ export function WorkspaceLauncher({
|
||||
<button
|
||||
type="button"
|
||||
role="menuitem"
|
||||
onClick={() => setWalletPanelOpen(true)}
|
||||
onClick={() => showLauncherNotice('会员与升级')}
|
||||
>
|
||||
会员与升级
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
role="menuitem"
|
||||
onClick={() => setLauncherView('guide')}
|
||||
onClick={() => showLauncherNotice('使用指南')}
|
||||
>
|
||||
使用指南
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
role="menuitem"
|
||||
onClick={() => setLauncherView('contact')}
|
||||
onClick={() => showLauncherNotice('反馈联系')}
|
||||
>
|
||||
反馈联系
|
||||
</button>
|
||||
@@ -3031,39 +3049,47 @@ export function WorkspaceLauncher({
|
||||
aria-label="帮助"
|
||||
title="帮助"
|
||||
className={
|
||||
['guide', 'contact', 'news'].includes(launcherView)
|
||||
helpMenuOpen || ['guide', 'contact', 'news'].includes(launcherView)
|
||||
? 'launcher-nav-active'
|
||||
: ''
|
||||
}
|
||||
aria-expanded={helpMenuOpen}
|
||||
onClick={() => {
|
||||
setAccountMenuOpen(false);
|
||||
setWalletPanelOpen(false);
|
||||
setHelpMenuOpen((open) => !open);
|
||||
}}
|
||||
>
|
||||
<CircleHelp size={17} aria-hidden="true" />
|
||||
</button>
|
||||
<div className="launcher-help-menu" role="menu">
|
||||
<button
|
||||
type="button"
|
||||
role="menuitem"
|
||||
onClick={() => setLauncherView('guide')}
|
||||
>
|
||||
<BookOpen size={14} aria-hidden="true" />
|
||||
使用指南
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
role="menuitem"
|
||||
onClick={() => setLauncherView('contact')}
|
||||
>
|
||||
<Contact size={14} aria-hidden="true" />
|
||||
联系我们
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
role="menuitem"
|
||||
onClick={() => setLauncherView('news')}
|
||||
>
|
||||
<Bell size={14} aria-hidden="true" />
|
||||
最新动态
|
||||
</button>
|
||||
</div>
|
||||
{helpMenuOpen ? (
|
||||
<div className="launcher-help-menu" role="menu">
|
||||
<button
|
||||
type="button"
|
||||
role="menuitem"
|
||||
onClick={() => showLauncherNotice('使用指南')}
|
||||
>
|
||||
<BookOpen size={14} aria-hidden="true" />
|
||||
使用指南
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
role="menuitem"
|
||||
onClick={() => showLauncherNotice('联系我们')}
|
||||
>
|
||||
<Contact size={14} aria-hidden="true" />
|
||||
联系我们
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
role="menuitem"
|
||||
onClick={() => showLauncherNotice('最新动态')}
|
||||
>
|
||||
<Bell size={14} aria-hidden="true" />
|
||||
最新动态
|
||||
</button>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
@@ -3101,9 +3127,13 @@ export function WorkspaceLauncher({
|
||||
<button
|
||||
type="button"
|
||||
aria-label="泥点余额"
|
||||
onClick={() => setWalletPanelOpen((open) => !open)}
|
||||
onClick={() => {
|
||||
setAccountMenuOpen(false);
|
||||
setHelpMenuOpen(false);
|
||||
setWalletPanelOpen((open) => !open);
|
||||
}}
|
||||
>
|
||||
<Wallet size={14} aria-hidden="true" />
|
||||
<Zap size={12} aria-hidden="true" />
|
||||
{formatMudPoints(profileDashboard?.walletBalance)}
|
||||
</button>
|
||||
{walletPanelOpen ? (
|
||||
@@ -3129,9 +3159,8 @@ export function WorkspaceLauncher({
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
<button type="button" onClick={() => setWalletPanelOpen(true)}>
|
||||
<CreditCard size={14} aria-hidden="true" />
|
||||
充值
|
||||
<button type="button" onClick={() => showLauncherNotice('升级')}>
|
||||
升级
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -3631,6 +3660,35 @@ export function WorkspaceLauncher({
|
||||
{runtimeConfigOpen ? (
|
||||
<RuntimeConfigDialog onClose={() => setRuntimeConfigOpen(false)} />
|
||||
) : null}
|
||||
{launcherNotice ? (
|
||||
<div
|
||||
className="launcher-dialog-backdrop"
|
||||
role="presentation"
|
||||
onMouseDown={(event) => {
|
||||
if (event.target === event.currentTarget) {
|
||||
setLauncherNotice(null);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<section
|
||||
aria-labelledby="launcher-notice-title"
|
||||
aria-modal="true"
|
||||
className="launcher-dialog"
|
||||
role="dialog"
|
||||
onKeyDown={(event) =>
|
||||
closeDialogOnEscape(event, () => setLauncherNotice(null))
|
||||
}
|
||||
>
|
||||
<h2 id="launcher-notice-title">{launcherNotice.title}</h2>
|
||||
<p>{launcherNotice.message}</p>
|
||||
<div className="launcher-dialog-actions">
|
||||
<button type="button" onClick={() => setLauncherNotice(null)}>
|
||||
知道了
|
||||
</button>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
) : null}
|
||||
{pendingNonEmptyProject ? (
|
||||
<div
|
||||
className="launcher-dialog-backdrop"
|
||||
|
||||
@@ -150,6 +150,7 @@ textarea {
|
||||
.launcher-sidebar {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 40;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
@@ -158,6 +159,7 @@ textarea {
|
||||
padding: 16px 0 18px;
|
||||
border-right: 1px solid #eceef2;
|
||||
background: #fff;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.launcher-brand {
|
||||
@@ -186,6 +188,7 @@ textarea {
|
||||
|
||||
.launcher-sidebar-bottom {
|
||||
position: relative;
|
||||
z-index: 60;
|
||||
display: grid;
|
||||
justify-items: center;
|
||||
gap: 13px;
|
||||
@@ -230,30 +233,18 @@ textarea {
|
||||
bottom: -4px;
|
||||
left: 36px;
|
||||
display: grid;
|
||||
min-width: 138px;
|
||||
gap: 4px;
|
||||
padding: 7px;
|
||||
min-width: 150px;
|
||||
gap: 5px;
|
||||
padding: 8px;
|
||||
border: 1px solid #e5e7eb;
|
||||
border-radius: 10px;
|
||||
border-radius: 8px;
|
||||
background: #fff;
|
||||
box-shadow: 0 14px 34px rgb(15 23 42 / 14%);
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
transform: translateX(-4px);
|
||||
transition:
|
||||
opacity 0.16s ease,
|
||||
transform 0.16s ease;
|
||||
z-index: 5;
|
||||
z-index: 90;
|
||||
}
|
||||
|
||||
.launcher-help-nav:hover .launcher-help-menu,
|
||||
.launcher-help-nav:focus-within .launcher-help-menu {
|
||||
opacity: 1;
|
||||
pointer-events: auto;
|
||||
transform: translateX(0);
|
||||
}
|
||||
|
||||
.launcher-sidebar .launcher-help-menu button {
|
||||
.launcher-sidebar .launcher-help-menu button,
|
||||
.launcher-sidebar .launcher-account-popover button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
@@ -269,7 +260,9 @@ textarea {
|
||||
}
|
||||
|
||||
.launcher-sidebar .launcher-help-menu button:hover,
|
||||
.launcher-sidebar .launcher-help-menu button:focus-visible {
|
||||
.launcher-sidebar .launcher-help-menu button:focus-visible,
|
||||
.launcher-sidebar .launcher-account-popover button:hover,
|
||||
.launcher-sidebar .launcher-account-popover button:focus-visible {
|
||||
background: #f3f4f6;
|
||||
}
|
||||
|
||||
@@ -333,7 +326,7 @@ textarea {
|
||||
right: 22px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 7px;
|
||||
gap: 0;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
@@ -345,11 +338,11 @@ textarea {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 5px;
|
||||
height: 24px;
|
||||
padding: 0 8px;
|
||||
border: 1px solid #e5e7eb;
|
||||
border-radius: 7px;
|
||||
gap: 4px;
|
||||
height: 26px;
|
||||
padding: 0 9px;
|
||||
border: 0;
|
||||
border-radius: 0;
|
||||
background: #fff;
|
||||
color: #1f2937;
|
||||
font-size: 12px;
|
||||
@@ -360,8 +353,9 @@ textarea {
|
||||
align-items: center;
|
||||
overflow: visible;
|
||||
border: 1px solid #e5e7eb;
|
||||
border-radius: 7px;
|
||||
border-radius: 8px;
|
||||
background: #fff;
|
||||
box-shadow: 0 1px 2px rgb(15 23 42 / 5%);
|
||||
}
|
||||
|
||||
.launcher-wallet-group > button,
|
||||
@@ -370,8 +364,14 @@ textarea {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.launcher-wallet-group .launcher-wallet-anchor > button {
|
||||
border-radius: 8px 0 0 8px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.launcher-wallet-group > button {
|
||||
border-left: 1px solid #e5e7eb;
|
||||
border-radius: 0 8px 8px 0;
|
||||
}
|
||||
|
||||
.launcher-wallet-anchor {
|
||||
@@ -393,7 +393,7 @@ textarea {
|
||||
background: #fff;
|
||||
box-shadow: 0 16px 38px rgb(15 23 42 / 14%);
|
||||
color: #111827;
|
||||
z-index: 9;
|
||||
z-index: 90;
|
||||
}
|
||||
|
||||
.launcher-account-nav .launcher-account-popover {
|
||||
@@ -401,6 +401,9 @@ textarea {
|
||||
right: auto;
|
||||
bottom: -4px;
|
||||
left: 36px;
|
||||
width: 218px;
|
||||
gap: 6px;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.launcher-account-popover strong,
|
||||
@@ -423,7 +426,7 @@ textarea {
|
||||
height: 30px;
|
||||
padding: 0 8px;
|
||||
border: 0;
|
||||
background: #f8fafc;
|
||||
background: transparent;
|
||||
color: #111827;
|
||||
}
|
||||
|
||||
@@ -1483,6 +1486,7 @@ textarea {
|
||||
.launcher-dialog-backdrop {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
z-index: 200;
|
||||
display: grid;
|
||||
padding: 24px;
|
||||
background: rgb(0 0 0 / 56%);
|
||||
|
||||
@@ -798,7 +798,7 @@ describe('AI 游戏创作 App 界面边界', () => {
|
||||
).not.toBeNull();
|
||||
expect(
|
||||
within(screen.getByLabelText('账户资产')).getByRole('button', {
|
||||
name: '充值',
|
||||
name: '升级',
|
||||
}),
|
||||
).not.toBeNull();
|
||||
expect(
|
||||
@@ -831,6 +831,34 @@ describe('AI 游戏创作 App 界面边界', () => {
|
||||
).toContain('/tmp/authorized-game');
|
||||
});
|
||||
|
||||
it('opens account and help menus by click and routes placeholder items to one notice dialog', () => {
|
||||
renderLauncherAt('/?launcher');
|
||||
|
||||
expect(
|
||||
screen.queryByRole('menuitem', { name: '联系我们' }),
|
||||
).toBeNull();
|
||||
fireEvent.click(screen.getByRole('button', { name: '帮助' }));
|
||||
expect(
|
||||
screen.getByRole('menuitem', { name: '联系我们' }),
|
||||
).not.toBeNull();
|
||||
fireEvent.click(screen.getByRole('menuitem', { name: '联系我们' }));
|
||||
expect(screen.getByRole('dialog', { name: '联系我们' })).not.toBeNull();
|
||||
expect(
|
||||
screen.getByText('联系我们正在接入中,当前版本会先保留入口。'),
|
||||
).not.toBeNull();
|
||||
fireEvent.click(screen.getByRole('button', { name: '知道了' }));
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: '我的' }));
|
||||
expect(
|
||||
screen.getByRole('menuitem', { name: '会员与升级' }),
|
||||
).not.toBeNull();
|
||||
fireEvent.click(screen.getByRole('menuitem', { name: '会员与升级' }));
|
||||
expect(screen.getByRole('dialog', { name: '会员与升级' })).not.toBeNull();
|
||||
expect(
|
||||
screen.getByText('会员与升级正在接入中,当前版本会先保留入口。'),
|
||||
).not.toBeNull();
|
||||
});
|
||||
|
||||
it('opens the developer agent chat entry and persists selected agent messages', async () => {
|
||||
const persistedMessages: Array<{
|
||||
role: 'user' | 'assistant' | 'tool';
|
||||
|
||||
Reference in New Issue
Block a user