Files
iAOP/web/shared/pro.css
T
bot_dev1 c0af291502 fix: 导航交互对齐 Ant Design Pro 体验(issue #131)
- 父级菜单整行点击 = 就地展开/收起 inline 子菜单(不再跳转),
  只有子项才导航,与 Pro 的 Menu inline 模式一致
- 子菜单展开加 max-height 过渡动画
- 菜单加 AntD Menu.ItemGroup 风格分组标题,hover 态补半透明白底
- 页内旧 topbar 去背景去边线,融入内容区当页标题行,消除双顶栏感
2026-08-05 16:20:52 +08:00

411 lines
13 KiB
CSS
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* iAOP 全站统一设计系统(Ant Design Pro 风格重构,2026-08)。
*
* 目标:整个 Web 前端(门户 / 登录 / 驾驶舱 / 配置台 / 管理台 / 助手 / 移动端)
* 统一为 Ant Design Pro 视觉语言——浅灰页面底 + 白色卡片 + AntD 5 蓝色主色,
* 字体 / 圆角 / 阴影 / 间距全部对齐 Ant Design 5 设计 token。
*
* 实现方式(纯静态、无构建链):
* 各模块页原本就用 CSS 变量调色(--cockpit-* 与 --bg/--surface/--fg 两套命名),
* 本文件在页面原有样式表【之后】加载,把这两套变量统一映射到 AntD 色板,
* 并统一字体、顶栏、按钮、输入框、表格、标签等基础元素外观,
* 各模块页业务逻辑与布局结构零改动。
*
* 色板来源:Ant Design 5 官方设计 token
* (primary #1677ff / success #52c41a / warning #faad14 / error #ff4d4f)。
*/
:root {
/* ---- Ant Design 5 基础 token --------------------------------------- */
--ant-primary: #1677ff;
--ant-primary-hover: #4096ff;
--ant-primary-active: #0958d9;
--ant-success: #52c41a;
--ant-warning: #faad14;
--ant-error: #ff4d4f;
--ant-text: rgba(0, 0, 0, 0.88);
--ant-text-secondary: rgba(0, 0, 0, 0.65);
--ant-text-tertiary: rgba(0, 0, 0, 0.45);
--ant-border: #d9d9d9;
--ant-split: rgba(5, 5, 5, 0.06);
--ant-bg-layout: #f0f2f5;
--ant-bg-container: #ffffff;
--ant-bg-fill: rgba(0, 0, 0, 0.04);
--ant-radius: 6px;
--ant-radius-lg: 8px;
--ant-shadow-card: 0 1px 2px 0 rgba(0, 0, 0, 0.03),
0 1px 6px -1px rgba(0, 0, 0, 0.02),
0 2px 4px 0 rgba(0, 0, 0, 0.02);
--ant-shadow-header: 0 1px 4px rgba(0, 21, 41, 0.08);
--ant-font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
"Helvetica Neue", Arial, "PingFang SC", "Hiragino Sans GB",
"Microsoft YaHei", "Noto Sans", sans-serif;
/* ---- iAOP 旧变量 → AntD 映射(cockpit/studio/mobile 用 --cockpit-*) -- */
--cockpit-bg: var(--ant-bg-layout);
--cockpit-surface: var(--ant-bg-container);
--cockpit-fg: var(--ant-text);
--cockpit-fg-muted: var(--ant-text-tertiary);
--cockpit-accent: var(--ant-primary);
--cockpit-warn: var(--ant-warning);
--cockpit-grid-line: var(--ant-split);
/* ---- iAOP 旧变量 → AntD 映射(admin/assistant/users 用短名) -------- */
--bg: var(--ant-bg-layout);
--surface: var(--ant-bg-container);
--surface-2: var(--ant-bg-fill);
--fg: var(--ant-text);
--fg-muted: var(--ant-text-tertiary);
--muted: var(--ant-text-tertiary);
--accent: var(--ant-primary);
--warn: var(--ant-warning);
--line: var(--ant-split);
}
/* ---- 全局排版 ---------------------------------------------------------- */
body {
font-family: var(--ant-font) !important;
-webkit-font-smoothing: antialiased;
font-size: 14px;
line-height: 1.5715;
}
/* ---- Ant Design Pro 左侧边栏布局(pro-header.js 注入) ------------------- */
/* 深色 Sider(#001529,AntD Pro 默认)+ 顶部白色细栏 + 内容区右移 */
.pro-sider {
position: fixed;
left: 0;
top: 0;
bottom: 0;
width: 208px;
background: #001529;
z-index: 20;
display: flex;
flex-direction: column;
box-shadow: 2px 0 6px rgba(0, 21, 41, 0.35);
transition: width 0.2s;
}
.pro-sider-logo {
display: flex;
align-items: center;
gap: 10px;
height: 48px;
padding: 0 16px;
text-decoration: none;
border-bottom: 1px solid rgba(255, 255, 255, 0.08);
flex-shrink: 0;
overflow: hidden;
white-space: nowrap;
}
.pro-sider-logo .pro-logo-badge {
width: 28px;
height: 28px;
border-radius: var(--ant-radius);
background: var(--ant-primary);
color: #fff;
font-size: 13px;
font-weight: 600;
display: flex;
align-items: center;
justify-content: center;
letter-spacing: 0.5px;
flex-shrink: 0;
}
.pro-sider-logo-text {
font-size: 15px;
font-weight: 600;
color: #fff;
overflow: hidden;
text-overflow: ellipsis;
}
.pro-sider-menu {
flex: 1;
overflow-y: auto;
padding: 8px 0;
}
.pro-menu-item {
display: flex;
align-items: center;
gap: 10px;
height: 40px;
margin: 4px 8px;
padding: 0 12px;
border-radius: var(--ant-radius);
color: rgba(255, 255, 255, 0.65);
text-decoration: none;
font-size: 14px;
white-space: nowrap;
overflow: hidden;
transition: background 0.2s, color 0.2s;
}
.pro-menu-item:hover { color: #fff; background: rgba(255, 255, 255, 0.08); }
.pro-menu-item.active {
background: var(--ant-primary);
color: #fff;
}
/* AntD Menu.ItemGroup 分组标题 */
.pro-menu-group-title {
padding: 10px 16px 4px;
font-size: 12px;
color: rgba(255, 255, 255, 0.45);
white-space: nowrap;
overflow: hidden;
}
.pro-menu-icon { font-size: 16px; flex-shrink: 0; width: 20px; text-align: center; }
.pro-menu-text { overflow: hidden; text-overflow: ellipsis; flex: 1; }
/* ---- SubMenu(模块子菜单,AntD Menu.SubMenu 风格) ----------------------- */
.pro-submenu-arrow {
font-size: 12px;
color: rgba(255, 255, 255, 0.45);
transition: transform 0.2s;
padding: 4px;
flex-shrink: 0;
}
.pro-submenu.open .pro-submenu-arrow { transform: rotate(90deg); }
.pro-submenu-items {
max-height: 0;
overflow: hidden;
transition: max-height 0.25s ease; /* AntD inline 菜单展开动画 */
background: #000c17; /* AntD 深色菜单子层底色 */
border-radius: var(--ant-radius);
margin: 0 8px 4px;
padding: 0;
}
.pro-submenu.open .pro-submenu-items { max-height: 320px; padding: 4px 0; }
.pro-subitem {
display: block;
height: 34px;
line-height: 34px;
padding: 0 12px 0 42px; /* 对齐父级文字(icon 20 + gap 10 + padding 12) */
margin: 2px 4px;
border-radius: 4px;
color: rgba(255, 255, 255, 0.65);
text-decoration: none;
font-size: 13px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
transition: background 0.2s, color 0.2s;
}
.pro-subitem:hover { color: #fff; background: rgba(255, 255, 255, 0.08); }
.pro-subitem.active {
background: var(--ant-primary);
color: #fff;
}
/* 父项在自身页面但未选子项时:不高亮整行,仅文字变白提示(AntD 语义) */
.pro-submenu-title.active { background: none; color: #fff; }
.pro-tabs-hidden { display: none !important; }
.pro-sider-trigger {
flex-shrink: 0;
height: 40px;
border: none !important;
border-top: 1px solid rgba(255, 255, 255, 0.08) !important;
border-radius: 0 !important;
background: transparent !important;
color: rgba(255, 255, 255, 0.65) !important;
font-size: 13px;
cursor: pointer;
text-align: center;
}
.pro-sider-trigger:hover { color: #fff !important; }
/* 内容区右移:Sider 固定定位,页面原内容整体让位 */
body.has-pro-sider { padding-left: 208px; transition: padding-left 0.2s; }
body.has-pro-sider.pro-sider-collapsed { padding-left: 48px; }
body.pro-sider-collapsed .pro-sider { width: 48px; }
body.pro-sider-collapsed .pro-sider-logo-text,
body.pro-sider-collapsed .pro-menu-text { display: none; }
body.pro-sider-collapsed .pro-menu-item { justify-content: center; padding: 0; }
body.pro-sider-collapsed .pro-sider-logo { justify-content: center; padding: 0; }
/* ---- 顶部白色细栏(页标题 + 用户区) ------------------------------------- */
.pro-header {
display: flex;
align-items: center;
gap: 16px;
height: 48px;
padding: 0 16px;
background: var(--ant-bg-container);
box-shadow: var(--ant-shadow-header);
position: relative;
z-index: 10;
}
.pro-header-page-title {
font-size: 16px;
font-weight: 600;
color: var(--ant-text);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.pro-header .pro-header-right {
margin-left: auto;
display: flex;
align-items: center;
gap: 12px;
font-size: 13px;
color: var(--ant-text-secondary);
}
.pro-header .pro-user {
display: flex;
align-items: center;
gap: 6px;
}
.pro-header .pro-avatar {
width: 24px;
height: 24px;
border-radius: 50%;
background: var(--ant-primary);
color: #fff;
font-size: 12px;
display: inline-flex;
align-items: center;
justify-content: center;
}
.pro-header .pro-logout {
border: none;
background: none;
color: var(--ant-text-tertiary);
cursor: pointer;
font-size: 13px;
padding: 4px 8px;
border-radius: var(--ant-radius);
font-family: inherit;
}
.pro-header .pro-logout:hover {
color: var(--ant-error);
background: var(--ant-bg-fill);
}
/* ---- AntD Tag(角色 / 状态标记) --------------------------------------- */
.pro-tag {
display: inline-block;
font-size: 12px;
line-height: 20px;
padding: 0 7px;
border-radius: 4px;
border: 1px solid transparent;
white-space: nowrap;
}
.pro-tag-blue { color: #1d39c4; background: #e6f4ff; border-color: #91caff; }
.pro-tag-green { color: #237804; background: #f6ffed; border-color: #b7eb8f; }
.pro-tag-gold { color: #ad6800; background: #fffbe6; border-color: #ffe58f; }
.pro-tag-red { color: #cf1322; background: #fff1f0; border-color: #ffa39e; }
.pro-tag-default{ color: var(--ant-text-secondary); background: #fafafa;
border-color: var(--ant-border); }
/* ---- 各模块页页内顶栏 → 融入内容区的页标题行 ----------------------------- */
/* 全局 Sider+细栏已就位,页内 #topbar 不再画成第二条导航条:
去背景去边线,视觉上只是内容区的页面标题行(AntD Pro PageContainer 语义) */
body.has-pro-sider #topbar {
background: transparent !important;
border-bottom: none !important;
box-shadow: none !important;
}
#topbar h1, #topbar h1 .sub { color: var(--ant-text) !important; }
#topbar h1 .sub { color: var(--ant-text-tertiary) !important; }
/* ---- 页内 tab(studio/admin)→ AntD Tabs 风格 -------------------------- */
.tab {
border: none !important;
border-radius: 0 !important;
background: transparent !important;
color: var(--ant-text-secondary) !important;
border-bottom: 2px solid transparent !important;
padding: 8px 4px !important;
margin: 0 12px;
}
.tab.active {
color: var(--ant-primary) !important;
background: transparent !important;
border-bottom-color: var(--ant-primary) !important;
}
/* ---- 表单控件 → AntD Input/Select 风格 --------------------------------- */
input:not([type="checkbox"]):not([type="radio"]),
select,
textarea {
font-family: inherit;
border: 1px solid var(--ant-border) !important;
border-radius: var(--ant-radius) !important;
background: var(--ant-bg-container) !important;
color: var(--ant-text) !important;
transition: border-color 0.2s, box-shadow 0.2s;
}
input:not([type="checkbox"]):not([type="radio"]):hover,
select:hover,
textarea:hover {
border-color: var(--ant-primary-hover) !important;
}
input:not([type="checkbox"]):not([type="radio"]):focus,
select:focus,
textarea:focus {
border-color: var(--ant-primary) !important;
outline: none;
box-shadow: 0 0 0 2px rgba(22, 119, 255, 0.1);
}
/* ---- 按钮 → AntD Button 风格 ------------------------------------------- */
button {
font-family: inherit;
border-radius: var(--ant-radius) !important;
border: 1px solid var(--ant-border);
background: var(--ant-bg-container);
color: var(--ant-text);
cursor: pointer;
transition: all 0.2s;
}
button:hover {
color: var(--ant-primary);
border-color: var(--ant-primary) !important;
}
button.primary, button.btn-primary, .btn-primary {
background: var(--ant-primary) !important;
border-color: var(--ant-primary) !important;
color: #fff !important;
}
button.primary:hover, button.btn-primary:hover, .btn-primary:hover {
background: var(--ant-primary-hover) !important;
border-color: var(--ant-primary-hover) !important;
}
button.danger, .btn-danger {
background: var(--ant-error) !important;
border-color: var(--ant-error) !important;
color: #fff !important;
}
button:disabled {
opacity: 0.55;
cursor: not-allowed;
}
/* ---- 表格 → AntD Table 风格 --------------------------------------------- */
table th {
background: #fafafa;
color: var(--ant-text-secondary) !important;
font-weight: 600 !important;
}
table th, table td {
border-bottom: 1px solid var(--ant-split) !important;
}
/* ---- 通用卡片(各页 .panel/.card 已用 --surface,此处补阴影圆角) ------- */
.panel, .card {
border: 1px solid var(--ant-split) !important;
border-radius: var(--ant-radius-lg) !important;
box-shadow: var(--ant-shadow-card);
}
/* ---- 对话助手气泡修正(亮底下的可读性) --------------------------------- */
.user .text { background: var(--ant-primary) !important; color: #fff !important; }
/* ---- 状态点(推理服务在线/离线) ---------------------------------------- */
.status-dot.ok, .dot.ok { color: var(--ant-success) !important; }
.status-dot.down, .dot.down { color: var(--ant-error) !important; }
/* ---- 窄屏适配:隐藏 Sider 退回纯顶栏 ------------------------------------- */
@media (max-width: 720px) {
.pro-sider { display: none; }
body.has-pro-sider, body.has-pro-sider.pro-sider-collapsed { padding-left: 0; }
.pro-header-page-title { font-size: 14px; }
}