feat: 重构侧栏布局,优化用户菜单和同步功能
This commit is contained in:
@@ -0,0 +1,12 @@
|
|||||||
|
# 侧栏与工作空间布局
|
||||||
|
Type: task
|
||||||
|
Status: resolved
|
||||||
|
|
||||||
|
## Scope
|
||||||
|
按 oppein-design-propotype 重构侧栏:230/64px、用户菜单、命令入口、最近访问、语义色与窄屏隐藏。右侧仅保留配置、Bot、同步任务三个图标,压缩顶部占用。保留业务页面与未提交改动,不部署。
|
||||||
|
|
||||||
|
## Validation
|
||||||
|
构建;侧栏展开/收起、最近访问关闭、用户菜单、三个入口、主题、窄屏与现有工作空间回归。
|
||||||
|
|
||||||
|
## Answer
|
||||||
|
已完成侧栏、用户菜单、快捷导航、最近访问及三个图标入口。保留现有平级业务导航,不新增语言系统或移动抽屉。构建通过;13 项相关端到端用例通过,最后的侧栏复验通过;已查看展开浅色、收起深色与窄屏截图。未部署。
|
||||||
@@ -479,60 +479,6 @@ export function AlphaPage({
|
|||||||
account?.connection_status === "expired";
|
account?.connection_status === "expired";
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="page-heading">
|
|
||||||
<div>
|
|
||||||
<h1>Alpha 管理</h1>
|
|
||||||
</div>
|
|
||||||
<div className="inline-actions">
|
|
||||||
<Button type="tertiary" onClick={() => setImporting(true)}>
|
|
||||||
导入 Alpha ID
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
theme="solid"
|
|
||||||
disabled={!connected}
|
|
||||||
onClick={() => {
|
|
||||||
setSyncingScope(submission);
|
|
||||||
onOverlay();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
按天同步
|
|
||||||
</Button>
|
|
||||||
{submission === "SUBMITTED" && (
|
|
||||||
<Button
|
|
||||||
loading={busy === "full_sync"}
|
|
||||||
disabled={!connected}
|
|
||||||
onClick={() => void newTask("full_sync")}
|
|
||||||
>
|
|
||||||
全量同步已提交
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="library-stats">
|
|
||||||
<div>
|
|
||||||
<span>已同步 Alpha</span>
|
|
||||||
<strong>{Number(facets.total ?? 0).toLocaleString()}</strong>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<span>我的收藏</span>
|
|
||||||
<strong>{Number(facets.favorites ?? 0).toLocaleString()}</strong>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<span>覆盖地区</span>
|
|
||||||
<strong>
|
|
||||||
{Array.isArray(facets.region) ? facets.region.length : 0}
|
|
||||||
</strong>
|
|
||||||
</div>
|
|
||||||
<div className="last-sync">
|
|
||||||
<span>最近数据更新</span>
|
|
||||||
<strong>
|
|
||||||
{formatTime(
|
|
||||||
typeof facets.last_sync === "string" ? facets.last_sync : null,
|
|
||||||
account?.timezone,
|
|
||||||
)}
|
|
||||||
</strong>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{!connected && (
|
{!connected && (
|
||||||
<Banner
|
<Banner
|
||||||
type="info"
|
type="info"
|
||||||
@@ -548,6 +494,7 @@ export function AlphaPage({
|
|||||||
)}
|
)}
|
||||||
{error && <Banner type="danger" description={error} />}
|
{error && <Banner type="danger" description={error} />}
|
||||||
<section className="library-panel" ref={tablePanel}>
|
<section className="library-panel" ref={tablePanel}>
|
||||||
|
<div className="alpha-tabs-header">
|
||||||
<Tabs
|
<Tabs
|
||||||
className="alpha-submission-tabs"
|
className="alpha-submission-tabs"
|
||||||
activeKey={submission}
|
activeKey={submission}
|
||||||
@@ -557,6 +504,16 @@ export function AlphaPage({
|
|||||||
{ itemKey: "SUBMITTED", tab: "已提交" },
|
{ itemKey: "SUBMITTED", tab: "已提交" },
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
|
<span className="alpha-last-sync">
|
||||||
|
最近数据更新{" "}
|
||||||
|
<span>
|
||||||
|
{formatTime(
|
||||||
|
typeof facets.last_sync === "string" ? facets.last_sync : null,
|
||||||
|
account?.timezone,
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
<SavedViews
|
<SavedViews
|
||||||
filters={{ ...filters, submission, sort, direction, limit: pageSize }}
|
filters={{ ...filters, submission, sort, direction, limit: pageSize }}
|
||||||
columns={visibleColumns}
|
columns={visibleColumns}
|
||||||
@@ -856,6 +813,34 @@ export function AlphaPage({
|
|||||||
导出
|
导出
|
||||||
</Button>
|
</Button>
|
||||||
</a>
|
</a>
|
||||||
|
<Button
|
||||||
|
size="small"
|
||||||
|
type="tertiary"
|
||||||
|
onClick={() => setImporting(true)}
|
||||||
|
>
|
||||||
|
导入 Alpha ID
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
size="small"
|
||||||
|
theme="solid"
|
||||||
|
disabled={!connected}
|
||||||
|
onClick={() => {
|
||||||
|
setSyncingScope(submission);
|
||||||
|
onOverlay();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
按天同步
|
||||||
|
</Button>
|
||||||
|
{submission === "SUBMITTED" && (
|
||||||
|
<Button
|
||||||
|
size="small"
|
||||||
|
loading={busy === "full_sync"}
|
||||||
|
disabled={!connected}
|
||||||
|
onClick={() => void newTask("full_sync")}
|
||||||
|
>
|
||||||
|
全量同步已提交
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
<Popover
|
<Popover
|
||||||
trigger="click"
|
trigger="click"
|
||||||
position="bottomRight"
|
position="bottomRight"
|
||||||
|
|||||||
+20
-37
@@ -161,36 +161,6 @@ label:not(.semi-checkbox):not(.semi-radio) {
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
.library-stats {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
flex-shrink: 0;
|
|
||||||
gap: var(--space-4);
|
|
||||||
padding: 0 0 var(--space-3);
|
|
||||||
flex-wrap: wrap;
|
|
||||||
}
|
|
||||||
.library-stats > div {
|
|
||||||
display: flex;
|
|
||||||
align-items: baseline;
|
|
||||||
gap: var(--space-2);
|
|
||||||
}
|
|
||||||
.library-stats span {
|
|
||||||
font-size: 12px;
|
|
||||||
color: var(--muted);
|
|
||||||
}
|
|
||||||
.library-stats strong {
|
|
||||||
font-size: 16px;
|
|
||||||
font-weight: 500;
|
|
||||||
font-variant-numeric: tabular-nums;
|
|
||||||
}
|
|
||||||
.library-stats .last-sync {
|
|
||||||
margin-left: auto;
|
|
||||||
}
|
|
||||||
.library-stats .last-sync strong {
|
|
||||||
font-size: 12px;
|
|
||||||
font-weight: 400;
|
|
||||||
color: var(--muted);
|
|
||||||
}
|
|
||||||
.library-panel {
|
.library-panel {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@@ -210,9 +180,28 @@ label:not(.semi-checkbox):not(.semi-radio) {
|
|||||||
max-height: 44%;
|
max-height: 44%;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
.alpha-submission-tabs {
|
.alpha-tabs-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: var(--space-2);
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
padding: 0 var(--space-3);
|
padding: 0 var(--space-3);
|
||||||
|
border-bottom: 1px solid var(--line);
|
||||||
|
}
|
||||||
|
.alpha-submission-tabs {
|
||||||
|
min-width: 0;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
.alpha-last-sync {
|
||||||
|
margin-left: auto;
|
||||||
|
padding: var(--space-2) 0;
|
||||||
|
color: var(--muted);
|
||||||
|
font-size: 12px;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
.alpha-last-sync > span {
|
||||||
|
display: inline-block;
|
||||||
|
font-variant-numeric: tabular-nums;
|
||||||
}
|
}
|
||||||
.alpha-submission-tabs .semi-tabs-content {
|
.alpha-submission-tabs .semi-tabs-content {
|
||||||
display: none;
|
display: none;
|
||||||
@@ -782,9 +771,6 @@ label:not(.semi-checkbox):not(.semi-radio) {
|
|||||||
.advanced-grid {
|
.advanced-grid {
|
||||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||||
}
|
}
|
||||||
.library-stats .last-sync {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.preferences-grid {
|
.preferences-grid {
|
||||||
grid-template-columns: 1fr 1fr;
|
grid-template-columns: 1fr 1fr;
|
||||||
}
|
}
|
||||||
@@ -804,9 +790,6 @@ label:not(.semi-checkbox):not(.semi-radio) {
|
|||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
}
|
}
|
||||||
.library-stats {
|
|
||||||
gap: var(--space-3);
|
|
||||||
}
|
|
||||||
.primary-filters {
|
.primary-filters {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 1fr 1fr;
|
grid-template-columns: 1fr 1fr;
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ test("submission tabs, day selection, local correlation and reload", async ({
|
|||||||
await page.getByLabel("密码", { exact: true }).fill("browser-test-password");
|
await page.getByLabel("密码", { exact: true }).fill("browser-test-password");
|
||||||
await page.getByRole("button", { name: "进入工作空间" }).click();
|
await page.getByRole("button", { name: "进入工作空间" }).click();
|
||||||
await expect(
|
await expect(
|
||||||
page.getByRole("heading", { name: "Alpha 管理", exact: true }),
|
page.getByRole("tab", { name: "待提交", exact: true }),
|
||||||
).toBeVisible();
|
).toBeVisible();
|
||||||
const headers = { "X-WQ-Request": "1" };
|
const headers = { "X-WQ-Request": "1" };
|
||||||
const credentials = await page.request.put("/api/v1/account/credentials", {
|
const credentials = await page.request.put("/api/v1/account/credentials", {
|
||||||
@@ -118,7 +118,9 @@ test("submission tabs, day selection, local correlation and reload", async ({
|
|||||||
await page.reload();
|
await page.reload();
|
||||||
await page.getByRole("textbox", { name: "搜索 Alpha" }).fill("TEST0004");
|
await page.getByRole("textbox", { name: "搜索 Alpha" }).fill("TEST0004");
|
||||||
await page.getByRole("button", { name: "查询", exact: true }).click();
|
await page.getByRole("button", { name: "查询", exact: true }).click();
|
||||||
await expect(page.locator(".alpha-table:visible")).toContainText("相关性偏高");
|
await expect(page.locator(".alpha-table:visible")).toContainText(
|
||||||
|
"相关性偏高",
|
||||||
|
);
|
||||||
await page.getByRole("tab", { name: "已提交", exact: true }).click();
|
await page.getByRole("tab", { name: "已提交", exact: true }).click();
|
||||||
await expect(
|
await expect(
|
||||||
page.getByRole("button", { name: "全量同步已提交" }),
|
page.getByRole("button", { name: "全量同步已提交" }),
|
||||||
|
|||||||
Reference in New Issue
Block a user