顶栏精简:移除 ⋯ 更多菜单,Mock 直达按钮 + 官网入口下沉侧栏

- 原 ⋯ 内容分流:设置/Mock/重置→设置弹窗已有;环境/主题/文档→顶栏已有按钮;
  自动化测试→侧栏底部已有;官网与价格→侧栏底部新增链接
- Mock 数据作为核心能力提升为顶栏一键直达(烧瓶图标 → 设置 Mock 页)
- 53 前端用例绿;顶栏近景截图评审通过
This commit is contained in:
logan committed 2026-09-18 11:51:27 +08:00
1 parent 17528a7e9d
commit 522e5d6300
4 files changed
+20 -81

No files matched your search

+11 -2
View File
@@ -115,8 +115,8 @@ export function Sidebar() {
)}
</div>
{/* 自动化测试入口 */}
<div className="p-2" style={{ borderTop: "1px solid var(--border)" }}>
{/* 自动化测试 / 官网入口 */}
<div className="space-y-1.5 p-2" style={{ borderTop: "1px solid var(--border)" }}>
<button
className="ops-btn ops-btn-secondary w-full"
onClick={() => useWorkspace.getState().setView("testing")}
@@ -124,6 +124,15 @@ export function Sidebar() {
>
<Icon name="list-checks" size={13} /> 自动化测试
</button>
<a
className="ops-btn ops-btn-ghost w-full text-[11px]"
href="/home"
target="_blank"
rel="noopener noreferrer"
title="官网与价格"
>
<Icon name="globe" size={11} /> 官网与价格
</a>
</div>
<ContextMenu menu={menu} onClose={() => setMenu(null)} />
+1 -1
View File
@@ -197,7 +197,7 @@ export function TestingView() {
<div className="ops-faint mt-1 text-xs leading-5">
手动编排 · AI 生成 · 定时调度,三种方式共用同一套场景用例
<br />
左侧新建用例,或从「⋯ 菜单 → 自动化测试」随时返回
左侧新建用例;侧栏底部「自动化测试」随时进出本视图
</div>
</div>
</div>
+8 -78
View File
@@ -1,5 +1,5 @@
/**
* 顶栏:logo / 新建 / 导入导出 / 环境 / 主题 / 文档 / 设置 / 更多。
* 顶栏:logo / 新建 / 导入导出 / 环境 / Mock / 账号 / 主题 / 文档 / 设置。
*/
import { useEffect, useState } from "react";
import { useWorkspace } from "../workspaceStore";
@@ -30,7 +30,6 @@ export function TopBar() {
const [newMenu, setNewMenu] = useState<{ x: number; y: number } | null>(null);
const [exportMenu, setExportMenu] = useState<{ x: number; y: number } | null>(null);
const [moreMenu, setMoreMenu] = useState<{ x: number; y: number } | null>(null);
const [spaceMenu, setSpaceMenu] = useState<{ x: number; y: number } | null>(null);
const [accountMenu, setAccountMenu] = useState<{ x: number; y: number } | null>(null);
const account = useWorkspace((s) => s.account);
@@ -154,68 +153,6 @@ export function TopBar() {
]
: [];
const moreItems: MenuItem[] = [
{
label: "设置…",
icon: <Icon name="settings" size={14} />,
onClick: () => setDialog({ type: "settings" }),
},
{
label: "Mock 数据…",
icon: <Icon name="flask-conical" size={14} />,
onClick: () => setDialog({ type: "settings", tab: "mock" }),
},
{
label: "自动化测试",
icon: <Icon name="list-checks" size={14} />,
onClick: () => useWorkspace.getState().setView("testing"),
},
{
label: "环境管理…",
icon: <Icon name="arrow-left-right" size={14} />,
onClick: () => setDialog({ type: "environments" }),
},
{
label: settings.theme === "dark" ? "切换到浅色主题" : "切换到深色主题",
icon: <Icon name={settings.theme === "dark" ? "sun" : "moon"} size={14} />,
onClick: () => setTheme(settings.theme === "dark" ? "light" : "dark"),
},
{ type: "sep" as const },
{
label: (
<span className="flex items-center gap-2">
用户文档
<Icon name="external-link" size={11} className="ops-faint" />
</span>
),
icon: <Icon name="book-open" size={14} />,
onClick: () => window.open("/docs", "_blank", "noopener,noreferrer"),
},
{
label: (
<span className="flex items-center gap-2">
官网与价格
<Icon name="external-link" size={11} className="ops-faint" />
</span>
),
icon: <Icon name="globe" size={14} />,
onClick: () => window.open("/home", "_blank", "noopener,noreferrer"),
},
{ type: "sep" as const },
{
label: "重置工作区…",
icon: <Icon name="trash" size={14} />,
danger: true,
onClick: () =>
setDialog({
type: "confirm",
title: "重置工作区",
message: "将恢复到初始示例数据,当前集合 / 环境 / 历史会被覆盖(建议先在「导出」中生成全量备份)。确定继续吗?",
action: () => useWorkspace.getState().resetWorkspace(),
}),
},
];
return (
<header
className="ops-panel ops-divider flex h-12 shrink-0 items-center justify-between gap-3 px-4"
@@ -286,6 +223,13 @@ export function TopBar() {
<button className="ops-btn ops-btn-ghost" onClick={() => setDialog({ type: "environments" })} title="环境管理">
<Icon name="settings" size={14} /> 环境
</button>
<button
className="ops-btn ops-btn-ghost"
onClick={() => setDialog({ type: "settings", tab: "mock" })}
title="Mock 数据:@表达式 + 智能匹配规则 + 预览"
>
<Icon name="flask-conical" size={15} />
</button>
<div className="mx-1 h-5 w-px" style={{ background: "var(--border)" }} />
@@ -352,16 +296,6 @@ export function TopBar() {
>
<Icon name="settings" size={15} />
</button>
<button
className="ops-btn ops-btn-ghost"
title="更多"
onClick={(e) => {
const rect = (e.currentTarget as HTMLElement).getBoundingClientRect();
setMoreMenu({ x: rect.right, y: rect.bottom + 4 });
}}
>
<Icon name="ellipsis" size={16} />
</button>
</div>
<ContextMenu
@@ -372,10 +306,6 @@ export function TopBar() {
menu={accountMenu ? { x: accountMenu.x, y: accountMenu.y, items: accountItems } : null}
onClose={() => setAccountMenu(null)}
/>
<ContextMenu
menu={moreMenu ? { x: moreMenu.x, y: moreMenu.y, items: moreItems } : null}
onClose={() => setMoreMenu(null)}
/>
<ContextMenu
menu={newMenu ? { x: newMenu.x, y: newMenu.y, items: newItems } : null}
onClose={() => setNewMenu(null)}