feat: add footer profile and upgrade dialogs

This commit is contained in:
2026-07-21 11:32:31 +08:00
parent 29dbaeddf0
commit b00cacd460
2 changed files with 166 additions and 29 deletions

View File

@@ -1893,9 +1893,9 @@
.statusbar { .statusbar {
height: 32px; height: 32px;
display: grid; display: grid;
grid-template-columns: minmax(310px, 0.9fr) minmax(480px, 1.2fr) minmax(320px, 0.9fr); grid-template-columns: minmax(180px, auto) minmax(0, 1fr);
align-items: center; align-items: center;
gap: 16px; gap: 20px;
padding: 0 16px; padding: 0 16px;
border-top: 1px solid rgba(255, 255, 255, 0.12); border-top: 1px solid rgba(255, 255, 255, 0.12);
background: var(--senlin-status); background: var(--senlin-status);
@@ -1917,6 +1917,18 @@
white-space: nowrap; white-space: nowrap;
} }
.status-user {
border: 0;
background: transparent;
color: rgba(255, 255, 255, 0.86);
padding: 0;
cursor: pointer;
}
.status-user:hover .status-name {
color: #fff;
}
.status-tasks { .status-tasks {
justify-content: center; justify-content: center;
} }
@@ -1931,6 +1943,7 @@
.status-system { .status-system {
justify-content: flex-end; justify-content: flex-end;
overflow: hidden;
} }
.status-name { .status-name {
@@ -1959,6 +1972,61 @@
color: #7be188; color: #7be188;
} }
.status-upgrade.arco-btn {
height: 22px;
padding: 0 10px;
border-radius: 999px;
font-size: 12px;
}
.status-modal-form {
margin-top: 8px;
}
.billing-plan-group {
width: 100%;
display: grid;
gap: 10px;
}
.billing-plan.arco-card {
cursor: pointer;
border-radius: 8px;
}
.billing-plan.active.arco-card {
border-color: var(--senlin-primary);
background: var(--senlin-soft-blue);
}
.billing-plan .arco-card-body {
padding: 12px;
}
.billing-plan .arco-radio {
width: 100%;
align-items: flex-start;
}
.billing-plan h6 {
margin: 0 0 4px;
}
.billing-price {
display: block;
margin-bottom: 4px;
color: var(--senlin-primary);
font-weight: 700;
}
.billing-payments {
display: grid;
gap: 10px;
margin-top: 16px;
border-top: 1px solid var(--senlin-border);
padding-top: 14px;
}
@media (max-width: 1180px) { @media (max-width: 1180px) {
.workbench-shell { .workbench-shell {
min-width: 1180px; min-width: 1180px;

View File

@@ -1,44 +1,113 @@
import { Avatar, Button, Layout, Space, Typography } 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 { import {
IconApps, IconApps,
IconCalendar, IconCalendar,
IconCheckCircleFill, IconCheckCircleFill,
IconMessage,
IconRobot, IconRobot,
IconSettings,
IconStorage, IconStorage,
IconThunderbolt, IconThunderbolt,
IconUserGroup, IconUser,
} from '@arco-design/web-react/icon' } from '@arco-design/web-react/icon'
const { Footer } = Layout const { Footer } = Layout
const { Text } = Typography 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() { export function ProjectStatusbar() {
const [profileOpen, setProfileOpen] = useState(false)
const [upgradeOpen, setUpgradeOpen] = useState(false)
const [selectedPlan, setSelectedPlan] = useState('pro')
return ( return (
<Footer className="statusbar"> <>
<div className="status-user"> <Footer className="statusbar">
<Avatar size={26} style={{ backgroundColor: '#165DFF' }}></Avatar> <button className="status-user" type="button" onClick={() => setProfileOpen(true)}>
<div className="status-identity"> <Avatar size={24} style={{ backgroundColor: '#165DFF' }}></Avatar>
<Text className="status-name"></Text> <span className="status-identity">
<span className="status-online-dot" aria-label="在线" title="在线" /> <Text className="status-name"></Text>
<span className="status-online-dot" aria-label="在线" title="在线" />
</span>
</button>
<Space className="status-system" size={18}>
<span><IconCheckCircleFill /> </span>
<span><IconInteractionFallback /> 3 </span>
<span><IconRobot /> AI </span>
<span><IconThunderbolt /> 稿</span>
<span><IconStorage /> 152GB </span>
<span> <b></b></span>
<Button className="status-upgrade" size="mini" type="primary" onClick={() => setUpgradeOpen(true)}></Button>
<IconApps />
</Space>
</Footer>
<Modal
title="个人资料"
visible={profileOpen}
onCancel={() => setProfileOpen(false)}
onOk={() => setProfileOpen(false)}
okText="保存"
cancelText="取消"
>
<Form layout="vertical" className="status-modal-form">
<Form.Item label="头像">
<Space>
<Avatar size={42} style={{ backgroundColor: '#165DFF' }}></Avatar>
<Button icon={<IconUser />}></Button>
</Space>
</Form.Item>
<Form.Item label="名称">
<Input defaultValue="张明" placeholder="请输入名称" />
</Form.Item>
<Form.Item label="邮箱">
<Input defaultValue="zhangming@senlin.ai" placeholder="请输入邮箱" />
</Form.Item>
<Form.Item label="当前密码">
<Input.Password placeholder="用于确认身份" />
</Form.Item>
<Form.Item label="新密码">
<Input.Password placeholder="不修改密码可留空" />
</Form.Item>
</Form>
</Modal>
<Modal
title="升级套餐"
visible={upgradeOpen}
onCancel={() => setUpgradeOpen(false)}
onOk={() => setUpgradeOpen(false)}
okText="去支付"
cancelText="取消"
>
<Radio.Group value={selectedPlan} onChange={setSelectedPlan} className="billing-plan-group">
{plans.map((plan) => (
<Card className={selectedPlan === plan.id ? 'billing-plan active' : 'billing-plan'} key={plan.id} bordered>
<Radio value={plan.id}>
<div>
<Title heading={6}>{plan.name}</Title>
<Text className="billing-price">{plan.price}</Text>
<Text type="secondary">{plan.desc}</Text>
</div>
</Radio>
</Card>
))}
</Radio.Group>
<div className="billing-payments">
<Text type="secondary"></Text>
<Space>
<Button></Button>
<Button></Button>
<Button></Button>
</Space>
</div> </div>
<Button type="text" icon={<IconUserGroup />}></Button> </Modal>
<Button type="text" icon={<IconMessage />}></Button> </>
<Button type="text" icon={<IconSettings />}></Button>
</div>
<Space className="status-tasks" size={28}>
<span><IconCheckCircleFill /> </span>
<span><IconInteractionFallback /> 3 </span>
<span><IconRobot /> AI </span>
<span><IconThunderbolt /> 稿</span>
</Space>
<Space className="status-system" size={24}>
<span><IconStorage /> 152GB </span>
<span> <b></b></span>
<IconApps />
</Space>
</Footer>
) )
} }