From d576ad02c1baa11ab2ae139dc260f1f011d6e197 Mon Sep 17 00:00:00 2001 From: yanweidong Date: Wed, 22 Jul 2026 15:42:58 +0800 Subject: [PATCH] feat(web): restore legacy status bar --- apps/web_v1/scripts/structure-check.mjs | 6 +- apps/web_v1/scripts/visual-check.mjs | 9 ++ apps/web_v1/src/App.css | 8 +- .../src/pages/projects/project-statusbar.tsx | 114 ++++++++++++++++-- 4 files changed, 128 insertions(+), 9 deletions(-) diff --git a/apps/web_v1/scripts/structure-check.mjs b/apps/web_v1/scripts/structure-check.mjs index e3a52af..66a5600 100644 --- a/apps/web_v1/scripts/structure-check.mjs +++ b/apps/web_v1/scripts/structure-check.mjs @@ -126,9 +126,13 @@ for (const required of ['explore-source-card', 'explore-reader-layout', '同步 if (!explorePageSource.includes(required)) failures.push(`workspace explore page must restore ${required}`) } +const statusbarSource = readFileSync('src/pages/projects/project-statusbar.tsx', 'utf8') +for (const required of ['status-online-dot', 'status-upgrade', 'status-system', '个人资料', '升级套餐']) { + if (!statusbarSource.includes(required)) failures.push(`project statusbar must restore ${required}`) +} + const unsupportedControls = [ { file: 'src/pages/projects/project-new-channel.tsx', required: '暂未开放', forbidden: ['保存频道', ' page.evaluate(() => { const statusbar = document.querySelector('.statusbar') const statusName = document.querySelector('.status-name') const statusOnlineDot = document.querySelector('.status-online-dot') + const statusUpgrade = document.querySelector('.status-upgrade') + const statusSystem = document.querySelector('.status-system') const search = document.querySelector('.global-search') const main = document.querySelector('.workbench-main') const workspacePage = document.querySelector('.workspace-page') @@ -146,6 +148,8 @@ const collectMetrics = async () => page.evaluate(() => { statusbarHeight: statusbar?.getBoundingClientRect().height, statusName: rect(statusName), statusOnlineDot: rect(statusOnlineDot), + statusUpgrade: rect(statusUpgrade), + statusSystemText: statusSystem?.textContent?.replace(/\s+/g, ' ').trim() ?? '', searchHeight: search?.getBoundingClientRect().height, workbenchMain: rect(main), hasWorkspacePage: Boolean(workspacePage), @@ -249,6 +253,11 @@ const metrics = workspaceMetrics if (errors.length) failures.push(`console errors: ${errors.join('; ')}`) if (metrics.statusbarHeight !== 32) failures.push(`expected statusbar height 32, got ${metrics.statusbarHeight}`) if (!metrics.statusName) failures.push('expected authenticated status label') +if (!metrics.statusOnlineDot) failures.push('expected legacy online status dot') +if (!metrics.statusUpgrade) failures.push('expected legacy upgrade action') +if (!metrics.statusSystemText.includes('3 个计划进行中') || !metrics.statusSystemText.includes('AI 空闲') || !metrics.statusSystemText.includes('152GB 可用')) { + failures.push(`expected legacy system status summary, got ${JSON.stringify(metrics.statusSystemText)}`) +} if (metrics.searchHeight !== 42) failures.push(`expected search height 42, got ${metrics.searchHeight}`) if (metrics.overflowX) failures.push('expected no horizontal overflow') if (!metrics.workbenchMain) failures.push('missing workbench main') diff --git a/apps/web_v1/src/App.css b/apps/web_v1/src/App.css index 3af913b..ca88279 100644 --- a/apps/web_v1/src/App.css +++ b/apps/web_v1/src/App.css @@ -2066,6 +2066,12 @@ .status-user { gap: 8px; +} + +.status-profile { + display: inline-flex; + align-items: center; + gap: 8px; border: 0; background: transparent; color: rgba(255, 255, 255, 0.86); @@ -2073,7 +2079,7 @@ cursor: pointer; } -.status-user:hover .status-name { +.status-profile:hover .status-name { color: #fff; } diff --git a/apps/web_v1/src/pages/projects/project-statusbar.tsx b/apps/web_v1/src/pages/projects/project-statusbar.tsx index 86b1254..dcf6736 100644 --- a/apps/web_v1/src/pages/projects/project-statusbar.tsx +++ b/apps/web_v1/src/pages/projects/project-statusbar.tsx @@ -1,14 +1,114 @@ -import { Layout } from '@arco-design/web-react' +import { useState } from 'react' +import { Avatar, Button, Card, Form, Input, Layout, Modal, Radio, Space, Typography } from '@arco-design/web-react' +import { + IconApps, + IconCalendar, + IconRobot, + IconStorage, + IconUser, +} from '@arco-design/web-react/icon' const { Footer } = Layout +const { Text, Title } = Typography + +const plans = [ + { id: 'starter', name: '基础版', price: '¥29/月', desc: '个人项目、基础智能体与 20GB 存储。' }, + { id: 'pro', name: '专业版', price: '¥99/月', desc: '团队协作、高级智能体与 200GB 存储。' }, + { id: 'team', name: '团队版', price: '¥299/月', desc: '成员管理、审计日志与私有化部署支持。' }, +] export function ProjectStatusbar() { + const [profileOpen, setProfileOpen] = useState(false) + const [upgradeOpen, setUpgradeOpen] = useState(false) + const [selectedPlan, setSelectedPlan] = useState('pro') + return ( -
-
- - 已登录 -
-
+ <> +
+
+ + +
+ + + 3 个计划进行中 + AI 空闲 + 152GB 可用 + 状态 正常 + + +
+ + setProfileOpen(false)} + onOk={() => setProfileOpen(false)} + okText="保存" + cancelText="取消" + > +
+ + + + + + + + + + + + + + + + + + +
+
+ + setUpgradeOpen(false)} + onOk={() => setUpgradeOpen(false)} + okText="去支付" + cancelText="取消" + > + + {plans.map((plan) => ( + + +
+ {plan.name} + {plan.price} + {plan.desc} +
+
+
+ ))} +
+
+ 支付方式 + + + + + +
+
+ ) } + +function IconInteractionFallback() { + return +}