顶栏精简:移除 ⋯ 更多菜单,Mock 直达按钮 + 官网入口下沉侧栏
- 原 ⋯ 内容分流:设置/Mock/重置→设置弹窗已有;环境/主题/文档→顶栏已有按钮; 自动化测试→侧栏底部已有;官网与价格→侧栏底部新增链接 - Mock 数据作为核心能力提升为顶栏一键直达(烧瓶图标 → 设置 Mock 页) - 53 前端用例绿;顶栏近景截图评审通过
This commit is contained in:
1 parent
17528a7e9d
commit
522e5d6300
4 files changed
+20
-81
No files matched your search
Binary file not shown.
@@ -115,8 +115,8 @@ export function Sidebar() {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</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
|
<button
|
||||||
className="ops-btn ops-btn-secondary w-full"
|
className="ops-btn ops-btn-secondary w-full"
|
||||||
onClick={() => useWorkspace.getState().setView("testing")}
|
onClick={() => useWorkspace.getState().setView("testing")}
|
||||||
@@ -124,6 +124,15 @@ export function Sidebar() {
|
|||||||
>
|
>
|
||||||
<Icon name="list-checks" size={13} /> 自动化测试
|
<Icon name="list-checks" size={13} /> 自动化测试
|
||||||
</button>
|
</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>
|
</div>
|
||||||
|
|
||||||
<ContextMenu menu={menu} onClose={() => setMenu(null)} />
|
<ContextMenu menu={menu} onClose={() => setMenu(null)} />
|
||||||
|
|||||||
@@ -197,7 +197,7 @@ export function TestingView() {
|
|||||||
<div className="ops-faint mt-1 text-xs leading-5">
|
<div className="ops-faint mt-1 text-xs leading-5">
|
||||||
手动编排 · AI 生成 · 定时调度,三种方式共用同一套场景用例
|
手动编排 · AI 生成 · 定时调度,三种方式共用同一套场景用例
|
||||||
<br />
|
<br />
|
||||||
左侧新建用例,或从「⋯ 菜单 → 自动化测试」随时返回
|
左侧新建用例;侧栏底部「自动化测试」随时进出本视图
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* 顶栏:logo / 新建 / 导入导出 / 环境 / 主题 / 文档 / 设置 / 更多。
|
* 顶栏:logo / 新建 / 导入导出 / 环境 / Mock / 账号 / 主题 / 文档 / 设置。
|
||||||
*/
|
*/
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { useWorkspace } from "../workspaceStore";
|
import { useWorkspace } from "../workspaceStore";
|
||||||
@@ -30,7 +30,6 @@ export function TopBar() {
|
|||||||
|
|
||||||
const [newMenu, setNewMenu] = useState<{ x: number; y: number } | null>(null);
|
const [newMenu, setNewMenu] = useState<{ x: number; y: number } | null>(null);
|
||||||
const [exportMenu, setExportMenu] = 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 [spaceMenu, setSpaceMenu] = useState<{ x: number; y: number } | null>(null);
|
||||||
const [accountMenu, setAccountMenu] = useState<{ x: number; y: number } | null>(null);
|
const [accountMenu, setAccountMenu] = useState<{ x: number; y: number } | null>(null);
|
||||||
const account = useWorkspace((s) => s.account);
|
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 (
|
return (
|
||||||
<header
|
<header
|
||||||
className="ops-panel ops-divider flex h-12 shrink-0 items-center justify-between gap-3 px-4"
|
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="环境管理">
|
<button className="ops-btn ops-btn-ghost" onClick={() => setDialog({ type: "environments" })} title="环境管理">
|
||||||
<Icon name="settings" size={14} /> 环境
|
<Icon name="settings" size={14} /> 环境
|
||||||
</button>
|
</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)" }} />
|
<div className="mx-1 h-5 w-px" style={{ background: "var(--border)" }} />
|
||||||
|
|
||||||
@@ -352,16 +296,6 @@ export function TopBar() {
|
|||||||
>
|
>
|
||||||
<Icon name="settings" size={15} />
|
<Icon name="settings" size={15} />
|
||||||
</button>
|
</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>
|
</div>
|
||||||
|
|
||||||
<ContextMenu
|
<ContextMenu
|
||||||
@@ -372,10 +306,6 @@ export function TopBar() {
|
|||||||
menu={accountMenu ? { x: accountMenu.x, y: accountMenu.y, items: accountItems } : null}
|
menu={accountMenu ? { x: accountMenu.x, y: accountMenu.y, items: accountItems } : null}
|
||||||
onClose={() => setAccountMenu(null)}
|
onClose={() => setAccountMenu(null)}
|
||||||
/>
|
/>
|
||||||
<ContextMenu
|
|
||||||
menu={moreMenu ? { x: moreMenu.x, y: moreMenu.y, items: moreItems } : null}
|
|
||||||
onClose={() => setMoreMenu(null)}
|
|
||||||
/>
|
|
||||||
<ContextMenu
|
<ContextMenu
|
||||||
menu={newMenu ? { x: newMenu.x, y: newMenu.y, items: newItems } : null}
|
menu={newMenu ? { x: newMenu.x, y: newMenu.y, items: newItems } : null}
|
||||||
onClose={() => setNewMenu(null)}
|
onClose={() => setNewMenu(null)}
|
||||||
|
|||||||
Reference in new issue
Block a user