@wildbuck/core-ui-frontend
v2.0.0-13
Published
Reusable console shell components and theme presets for Buck business applications.
Readme
@wildbuck/core-ui-frontend
@wildbuck/core-ui-frontend 面向独立业务前端壳,提供 Buck 控制台通用布局组件、导航辅助函数、主题预设和 CSS token。
入口
@wildbuck/core-ui-frontend/theme.css:控制台主题 token、shell 布局、菜单、顶部栏、主题化滚动条(--console-scrollbar-*)、Element Plus 变量联动。@wildbuck/core-ui-frontend/theme:createBrickConsoleThemePresets()、resolveBrickConsoleBrowserThemeColor()/applyBrickConsoleBrowserChromeTheme()(PWA/浏览器标题栏用 topbar 色,不用 accent)、以及 appearance 规范化导出。@wildbuck/core-ui-frontend/shell:BrickConsoleShell、BrickConsoleSidebar、BrickConsoleDrawer、BrickConsoleTopbar、BrickConsoleContextHeader、BrickConsoleSidebarCollapseToggle、BrickConsoleNavIcon、BrickUserMenu、BrickAppearanceSettingsDialog、BrickAppearanceSwitcher,以及shell-navigation/shell-icons辅助函数。@wildbuck/core-ui-frontend/pwa:PWA 安装引导。壳层优先用useBrickPwaInstall({ vue, serviceWorkerUrl, onUnavailable }),直接绑定canInstallApp+installApp到BrickConsoleShell/BrickUserMenu;底层仍导出createBrickPwaInstallController、registerBrickPwaServiceWorker。业务壳提供 manifest/图标/Service Worker 文件与匿名访问;BRICK_PWA_INSTALL_UNAVAILABLE_MESSAGE可作不可安装时的默认提示文案。- 验收:Buck 承诺的是用户菜单「安装应用」+
beforeinstallprompt;Chrome 地址栏安装图标不是必现,不能当验收标准。 - 注册时机:优先在入口
main尽早registerBrickPwaServiceWorker(或给useBrickPwaInstall传serviceWorkerUrl),不要等业务路由才注册。 - Vite 开发态 SW:install/activate + 透明
fetch透传即可;禁止 cache-first /cache.addAll劫持/src与 HMR。完整清单与样例见交付文档business-frontend-ui-reference.md「PWA 安装与 Vite 开发态」。
- 验收:Buck 承诺的是用户菜单「安装应用」+
@wildbuck/core-ui-frontend/workspace-profile(亦从shell导出):工位视图 / Workspace Profile 纯函数与BrickWorkspaceProfileSelect。只做 UI 焦点过滤,不换 token、不改 IAM 权限;过滤结果必须是principal.permissions可访问集合的子集。业务提供 profiles 配置。@wildbuck/core-ui-frontend/i18n:壳层官方词条(zh-CN/en-US)、useBrickConsoleI18n/resolveBrickConsoleUiMessages;业务壳providei18n runtime 并registerMessages('core-ui', …),组件内通过 inject 取t()。侧栏菜单 title 来自导航/菜单数据原文,不在 core-ui 词条内翻译。@wildbuck/core-ui-frontend/fields:BrickReadonlyCopyInput、BrickManagedSecretInput、BrickImageUploadField,以及resolveBrickManagedSecretField()helper,用于只读复制、敏感凭据编辑、图片上传预览等高频字段模式。@wildbuck/core-ui-frontend/patterns:BrickFilterToolbar、BrickPageBlock、BrickEmptyState、BrickPaginationBar、BrickActionBar、BrickRiskConfirm、BrickSettingsCard、BrickSettingsDrawer等页面模式组件,用于代码化 block/action 页面组合。
最小接入
import '@wildbuck/core-ui-frontend/theme.css';
import { BrickConsoleDrawer, BrickConsoleShell } from '@wildbuck/core-ui-frontend/shell';
import {
BrickImageUploadField,
BrickManagedSecretInput,
BrickReadonlyCopyInput,
resolveBrickManagedSecretField,
} from '@wildbuck/core-ui-frontend/fields';
import {
BrickActionBar,
BrickFilterToolbar,
BrickPageBlock,
BrickPageHeader,
BrickPaginationBar,
BrickSettingsCard,
BrickStatStrip,
} from '@wildbuck/core-ui-frontend/patterns';业务前端壳只覆盖业务品牌 token 和业务页面,不要复制 validation/security-console 内部实现,也不要深度引入未导出的模块文件。
统一交互规则:
- 保存、提交、确认这类底部动作优先使用
BrickActionBar,不要在页面里各写一套.form-actions、.footer-actions。 - 表单、配置卡片和抽屉的底部按钮默认右下收口,
secondary在左、primary在右、danger最后;BrickActionBar默认是无外框的plain表达,只有需要独立卡片化动作区时才显式使用surface="framed"。 - 服务端分页的列表必须使用
BrickPaginationBar,不要在模块或业务仓库里各写一套“上一页 / 下一页”或裸el-pagination样式。 - 删除、全部下线、重置密码、重置密钥等高风险动作优先使用
BrickRiskConfirm,不要直接裸放危险按钮。 - 同一字段的必填提示只能保留一套星号来源;共享必填标签样式和
el-form-item required不要叠加。 - 敏感值在列表、详情只读区和摘要区默认脱敏;需要修改时,先让用户显式进入编辑态。
控制台壳默认气质
侧栏与顶栏默认按治理型正式后台收口,而不是验证演示壳:
- 品牌区:实色小标,不用渐变营销块;副标题可空。
- 导航:低饱和 active + 左侧指示条;字母 mark 弱化,优先真实图标。
- 顶栏:约 48px 扁平工具条;刷新/全屏为图标按钮 +
title/aria-label。 - 默认
blue主题为克制蓝灰浅侧栏;其它主题保留但非默认。
圆角层级
Buck 默认界面是治理型后台,圆角用于表达层级,不作为装饰风格铺满页面。
- 结构层使用
0或近直角:顶部栏、侧栏、整页分区、表格贴边区域和抽屉外框优先保持清晰边界。 - 控件层使用
--console-field-radius: 6px:输入框、按钮、筛选控件和紧凑操作项保持可点击但不过度柔化。 - 圆角刻度:
--console-field-radius: 4px、--console-card-radius: 8px、--console-block-radius: 4px、--console-pill-radius: 999px(仅真胶囊)。抽屉内详情区禁止再叠一层圆角卡。 - 强调型提示如确有必要可以使用
--console-notice-radius,但模块页面不得直接硬编码9px以上圆角。 - 状态丸、标签、徽标和头像类圆形元素使用
--console-pill-radius: 999px或50%;不要把普通卡片、按钮和选择面板做成胶囊。
Block / Action 页面模式
patterns 只沉淀代码化页面模式,不是低代码运行时平台。core-ui 负责布局、密度、主题 token、加载态、空状态、错误反馈、动作区和危险确认;查询字段白名单、操作符、排序和分页上限仍归 core:query,下拉和标签选项仍归 core:option / BrickOptionProvider,按钮是否可见或可执行仍由模块页面或业务页面判断。组件不读取权限目录,不发起业务请求,也不接收后端返回的运行时 UI schema。
第一批公开 block/action:
BrickFilterToolbar:列表页筛选字段和筛选动作区。BrickPageHeader:紧凑后台页眉(title / description / actions;可选 eyebrow);主操作放#actions,指标放#stats,禁止营销向超大标题作为默认。BrickListPageActions:页眉列表动作槽,顺序#extra→#import→#export→#primary(新增最右 solid);筛选条禁止放新增/导入/导出。BrickSelectionActionBar:表格多选条(selectedCount、#batch、#clear)。BrickImportExportMenu:可选 plain「导入/导出」下拉。BrickStatStrip:可选指标条;只展示 label/value/tone,不占用主操作位,也不计算业务指标。BrickPageBlock:页面任务块,统一标题、说明、加载、错误、空状态、actions 和 footer slot。BrickEmptyState:无数据、无权限、筛选无结果或加载失败的可恢复提示。BrickPaginationBar:服务端分页列表的总数、每页条数、上一页、下一页、页码和跳页动作。BrickActionBar:页面、配置表单或抽屉底部的主动作、次动作、批量动作和危险动作布局。BrickRiskConfirm:删除、强制登出、重置密钥等危险操作确认弹窗;组件只发出confirm事件,业务执行和失败恢复由页面负责。BrickStepUpConfirm:敏感操作前输入当前密码再确认;通过verify(password)调用框架POST /brick/session/verify-password(可用verifySessionPasswordhelper),成功只emit('success'),不把密码回传业务。密码框与弹窗表面须使用--console-*token,不写死亮色。BrickTableMoreMenu:列表操作列「更多」下拉壳,默认三点图标触发器(iconOnly,操作列末位);危险/敏感项放 menu item,执行前外层接 step-up。BrickSettingsGrid/BrickSettingsCard/BrickSettingsDrawer/BrickSettingsDrawerSection:设置表单页的目录卡片、抽屉和分组骨架;状态、摘要、保存逻辑和权限语义仍由模块页面负责。BrickSettingsEnableSwitch/BrickSettingsScale/BrickSettingsSegmentChoice/BrickSettingsCheckGrid/BrickSettingsPreview/BrickSettingsStaticNote:配置抽屉内的高频控件组合;只统一 Element Plus 控件布局、说明层级、预览区和主题 token,不提供选项源、校验规则或业务请求。BrickPolicyGrid/BrickPolicyCard/BrickPolicyDrawer/BrickPolicyDrawerSection等旧策略命名继续作为兼容别名导出,以避免已发布调用方破坏;新代码应优先使用BrickSettings*。
列表页骨架
治理列表页推荐结构:页眉 → 筛选 → 任务块(表格 + 分页)。指标若确有必要,放在页眉 #stats,不要塞进 #actions。
<article class="list-page">
<BrickPageHeader
eyebrow="系统管理 / 员工管理"
title="员工管理"
description="先筛选并找到员工,再处理资料、角色和会话。"
>
<template #actions>
<el-button type="primary" @click="openCreateDrawer">新增员工</el-button>
</template>
<template #stats>
<BrickStatStrip
:items="[
{ label: '员工总数', value: total },
{ label: '活跃会话', value: activeSessionCount, tone: 'success' },
]"
/>
</template>
</BrickPageHeader>
<BrickFilterToolbar>
<!-- 筛选字段由页面持有;查询 DSL 仍归 core:query -->
<template #actions>
<el-button @click="resetFilters">重置</el-button>
<el-button type="primary" @click="applyFilters">筛选</el-button>
</template>
</BrickFilterToolbar>
<BrickPageBlock
:loading="loading"
:empty="rows.length === 0"
empty-title="暂无数据"
empty-description="创建第一条数据后再继续配置后续动作。"
:bordered="false"
>
<el-table :data="rows" />
<template #footer>
<BrickPaginationBar
:page="page"
:page-size="pageSize"
:total="total"
:page-sizes="[10, 20, 50, 100]"
@update:page="changePage"
@update:page-size="changePageSize"
/>
</template>
</BrickPageBlock>
</article>内容区任务块也可单独使用:
<BrickPageBlock
title="数据项管理"
description="维护当前页面的对象列表、筛选结果和批量操作。"
:loading="loading"
:empty="rows.length === 0"
empty-title="暂无数据"
empty-description="创建第一条数据后再继续配置后续动作。"
>
<template #actions>
<el-button type="primary" @click="openCreateDrawer">新增</el-button>
</template>
<el-table :data="rows" />
<template #footer>
<BrickActionBar>
<template #secondary>
<el-button @click="reset">重置</el-button>
</template>
<template #primary>
<el-button type="primary" :loading="saving" @click="save">保存</el-button>
</template>
</BrickActionBar>
</template>
</BrickPageBlock>设置表单页模式
登录安全、密码策略、传输安全和类似“先选择设置场景、再进入抽屉配置”的页面,应使用 BrickSettings* 组件,不要在模块里复制一套卡片、抽屉、滑块、单选、多选和预览样式。组件样式只使用 --console-* 与 Element Plus 变量,因此会跟随 BrickConsoleShell 的主题、字号和密度设置。
<BrickSettingsGrid data-guide-anchor="summary">
<BrickSettingsCard
title="密码强度"
description="设置密码长度和字符要求。"
status-label="已启用"
@open="openStrengthDrawer"
/>
</BrickSettingsGrid>
<BrickSettingsDrawer
v-model="drawerVisible"
title="密码强度"
description="设置密码长度和字符要求。"
@save="saveStrength"
>
<BrickSettingsDrawerSection title="强度规则" description="定义长度和字符组合。">
<el-form label-position="top" class="setting-form brick-required-form">
<BrickSettingsEnableSwitch
v-model="enabled"
class="setting-form__full"
label="强度规则状态(必填)"
description="启用后校验密码强度。"
/>
<BrickSettingsScale
v-model="minLength"
class="setting-form__full"
label="最小长度(必填)"
unit=" 位"
:min="6"
:max="32"
:marks="[{ value: 8, label: '8' }, { value: 16, label: '16' }]"
/>
<!-- Prefer BrickSettingsScale over raw el-slider; mark geometry is owned by the component. -->
</el-form>
</BrickSettingsDrawerSection>
</BrickSettingsDrawer>规则:
- 模块页面提供业务文案、状态、选项、保存和风险确认;
BrickSettings*不读取权限、不开请求、不绑定具体业务模块。 - 操作按钮使用标准
ElButton type="primary",颜色由主题映射到 Element Plus 变量;不要在模块 CSS 中重写按钮颜色。 - 字段仍需显式标注
(必填)/(选填),并继续配合brick-required-form使用统一必填星号。
<BrickRiskConfirm
title="确认删除"
description="该操作会影响当前选中的数据。"
impact="删除后需要通过业务恢复流程找回。"
confirm-text="确认删除"
:loading="removing"
@confirm="removeSelected"
>
<template #trigger>
<el-button type="danger" plain>删除</el-button>
</template>
</BrickRiskConfirm>标准筛选工具条
列表页、审计页和应用中心这类“筛选 + 表格/列表”页面应使用 BrickFilterToolbar 承载筛选字段和操作按钮,不要在模块或业务仓库复制 .filter-bar、.query-toolbar 这类泛化 CSS。查询字段、文案和控件仍由页面自己定义;BrickFilterToolbar 只统一布局、间距、按钮高度和主题 token。
布局 vs 状态(重要)
| 能力 | 归属 |
| --- | --- |
| 字段网格 + 动作区布局 | BrickFilterToolbar |
| 草稿 / 查询 / 重置清空 | useBrickFilterDraft(同包 patterns 导出) |
| 具体筛选项(组织、启用…) | 模块 *FilterToolbar,不进 core |
不要把父组件的 filters 直接 v-model 到 prop 字段上再期望「重置」清空输入框——这是「输入框不清」的常见根因。控件只绑 draft,查询/重置时用 snapshot() / resetDraft() 回写父级。
架构细则见 docs/architecture/capabilities/frontend-structure.md「列表筛选」。
日期和时间筛选优先使用 Element Plus ElDatePicker / el-date-picker,不要使用原生 input[type=date] 或 input[type=datetime-local] 让用户手填。Element Plus daterange / datetimerange 字段把 brick-filter-toolbar__field--range 加在直接 grid item 上后会跨两列,小屏下占满整行;如果外层包了 el-form-item、本地 wrapper 或其他字段容器,就把该 class 放在外层直接 grid item 上。actions 插槽可以直接放 BrickActionBar,toolbar 会移除它作为底部动作区时的顶部留白,不需要业务页再写局部 padding 覆盖。
<script setup>
import { BrickFilterToolbar, useBrickFilterDraft } from '@wildbuck/core-ui-frontend/patterns';
const emit = defineEmits(['update:modelValue', 'search', 'reset']);
const { draft, resetDraft, snapshot } = useBrickFilterDraft(() => ({
keyword: '',
createdAtRange: null,
}));
function search() {
const next = snapshot();
emit('update:modelValue', next);
emit('search', next);
}
function reset() {
const next = resetDraft();
emit('update:modelValue', next);
emit('reset', next);
}
</script>
<template>
<!-- 不要用 form 包筛选栏;按钮一律 native-type="button" -->
<BrickFilterToolbar field-min-width="180px" data-guide-anchor="filters">
<el-input v-model="draft.keyword" placeholder="关键字" clearable @keyup.enter="search" />
<el-date-picker
v-model="draft.createdAtRange"
class="brick-filter-toolbar__field--range"
type="datetimerange"
value-format="YYYY-MM-DD HH:mm:ss"
format="YYYY-MM-DD HH:mm:ss"
start-placeholder="开始时间"
end-placeholder="结束时间"
clearable
/>
<template #actions>
<BrickActionBar>
<template #secondary>
<el-button native-type="button" @click="reset">清空条件</el-button>
</template>
<template #primary>
<el-button type="primary" native-type="button" @click="search">开始筛选</el-button>
</template>
</BrickActionBar>
</template>
</BrickFilterToolbar>
</template>规则:
- 只要筛选条件需要服务端请求、服务端分页、审计追溯或成本较高查询,就必须提供显式查询按钮;重置或清空在左,查询或筛选在右。
- 只有纯本地树、纯前端小集合即时过滤,且不会触发远端请求时,才可以不放查询按钮。
- 不要渲染尚未接入真实查询字段的禁用筛选控件;未实现的筛选应隐藏,等后端 DTO、
core:query定义和页面逻辑都具备后再开放。 - 控件绑定 draft,不绑定父 prop 字段;否则重置后输入框经常「看起来没清空」。
标准分页条
服务端分页列表必须使用 BrickPaginationBar。它只负责分页控件布局和事件,不发起请求,不保存查询条件,也不决定后端分页上限;这些仍归模块页面和 core:query。
<BrickPaginationBar
:page="page"
:page-size="pageSize"
:page-sizes="[10, 20, 50, 100]"
:summary="pageSummary"
:total="total"
@update:page="changePage"
@update:page-size="changePageSize"
/>规则:
- 服务端分页列表只要
total > pageSize或列表语义本身支持翻页,就显示分页条;不要只提供“上一页 / 下一页”。 - 服务端分页列表默认每页条数选项为
[10, 20, 50, 100];卡片流、纯本地列表等非标准表格可以在页面内说明后使用更贴合布局的选项。 - 每页条数属于分页条,不放在筛选字段区,避免把查询条件和分页控制混成一组。
- 总数只在左侧
summary区域表达;未传summary时默认显示共 ${total} 条,右侧分页控件不再开启 Element Plus 内置total,避免出现重复总数。 - 默认使用 Element Plus
zh-cnlocale,中文后台不应出现Total、/page、Go to这类英文默认文案;多语言宿主可通过localeprop 覆盖。 - 纯本地树、小型配置清单、固定少量选项列表可以不分页;如果未来数据来源变成服务端分页,再切换到
BrickPaginationBar。 - 表格列较多或可能出现横向滚动时,操作列固定在右侧;这样用户无需拖到最右才能发现可执行动作。
只读复制字段
clientSecret、API Key、Webhook Secret,以及员工手机号、邮箱、身份证号等敏感值展示应使用 BrickReadonlyCopyInput,不要在业务仓库自建 CopyInput、SecretInput 或复制按钮组合。
<BrickReadonlyCopyInput
label="Client Secret"
:model-value="createdSecret"
description="明文只在创建后展示一次。"
@copied="handleSecretCopied"
/>详情页只允许展示脱敏文本时,使用 masked;如果确实需要复制真实值,必须由后端重新签发或返回明确允许复制的 copy-text。
<BrickReadonlyCopyInput
label="Client Secret"
masked
mask-text="明文仅展示一次"
:copyable="false"
/>员工、主体、联系人等个人敏感信息遵循同一条规则:列表页、详情只读区和摘要区默认展示脱敏值;如果业务允许修改,先通过“修改敏感信息”之类的显式动作切换到编辑输入框。
敏感凭据编辑字段
首次录入后不回显明文、再次编辑留空表示不修改的字段,应使用 BrickManagedSecretInput 和 resolveBrickManagedSecretField(),不要在业务仓库自建 SensitiveCredentialInput 或把页面级 configured 误当成字段级托管状态。
<script setup>
import { computed, ref } from 'vue';
import {
BrickManagedSecretInput,
resolveBrickManagedSecretField,
} from '@wildbuck/core-ui-frontend/fields';
const form = ref({ appSecret: '' });
const detail = ref({ appSecretConfigured: true });
const appSecretField = computed(() => resolveBrickManagedSecretField({
label: '应用密钥',
configured: Boolean(detail.value?.appSecretConfigured),
value: form.value.appSecret,
unconfiguredPlaceholder: '填写应用密钥',
}));
</script>
<template>
<el-form-item :label="appSecretField.labelText" :required="appSecretField.required">
<BrickManagedSecretInput
v-model="form.appSecret"
aria-label="应用密钥"
:configured="appSecretField.configured"
unconfigured-placeholder="填写应用密钥"
/>
</el-form-item>
</template>规则:
configured必须来自字段级xxxConfigured、credentialMasked或同义后端字段,不要用“整张配置是否存在”代替。- 首次创建时组件按必填语义工作;已托管后自动切换为选填,并显示“留空表示不修改”的正式提示。
- 保存请求继续由业务页面或模块 API 构造;
resolveBrickManagedSecretField()只负责 required/optional、placeholder、hint、validationValue和submitValue。 - 明文仍只存在于当前编辑输入框;组件不回显后端明文,也不从掩码文本反推历史值。
颜色字段
主色、背景色等 hex 色值编辑使用 BrickColorField(色板 + hex 输入,高度对齐):
<script setup>
import { BrickColorField } from '@wildbuck/core-ui-frontend/fields';
</script>
<BrickColorField v-model="primaryColor" placeholder="#0d9488" />不要在业务页复制 el-color-picker + el-input 的局部 CSS。验证壳等按需注册场景需全局注册 ElColorPicker。
图片上传字段
员工头像、菜单图标、应用 Logo、登录品牌图等共享图片资源上传应使用 BrickImageUploadField。组件负责文件选择、安全预览、按钮交互、类型和大小校验;上传接口、资源分类和保存时机由业务模块负责。
<script setup>
import {
BrickImageUploadField,
createBrickLocalImagePreview,
revokeBrickImagePreview,
uploadBrickImageResource,
} from '@wildbuck/core-ui-frontend/fields';
// 业务表只存 resourceId。previewUrl 只能是 blob: 或公开匿名 URL,不能是 contentUrl。
async function onUpload(file) {
const uploaded = await uploadBrickImageResource(file, 'APPLICATION_LOGO');
resourceId.value = uploaded.resourceId;
previewUrl.value = createBrickLocalImagePreview(file); // 勿用 uploaded.contentUrl
}
</script>
<BrickImageUploadField
label="应用 Logo"
description="系统会先上传共享资源,再在保存应用时绑定。"
:preview-url="previewUrl"
:uploading="logoUploading"
upload-text="上传 Logo"
clear-text="清除 Logo"
@upload="onUpload"
@clear="onClear"
/>预览规则:
GET /file-resources/{id}/content需要认证,禁止作为裸<img src>(会 401)。- 未保存:
createBrickLocalImagePreview(file)或依赖组件在选文件后自动建立的本地blob:预览。 - 已保存需鉴权读:
loadBrickImageResourcePreviewUrl(resourceId)(内部requestBlob)。 - 登录页等匿名场景:用功能点提供的 public 路径,不要放行 content 端点。
默认支持 png、jpg、gif、webp、svg,文件大小上限 2MB。配置页双列布局使用 @wildbuck/core-ui-frontend/settings-page.css 的 .brick-detail-form / .setting-form。业务应用不要自建隐藏 file input + 预览块组合。
统一状态反馈
根入口和 @wildbuck/core-ui-frontend/status 子入口都导出两个高频无界面能力;只需要状态反馈时优先使用 status 子入口,避免把无关 UI 入口带进首屏包:
showBrickStatus(message, type, options):统一 Element Plus toast,适合保存成功、保存失败、危险恢复建议等瞬时反馈。validateBrickRequiredFields(fields, options):保存前的本地必填校验;校验失败时会统一弹出 toast,并尽量聚焦首个非法字段。theme.css:同时提供brick-required-form和console-required-label两个正式必填标识入口,统一el-form-item required与自定义标签行的红色星号。
推荐规则:
- 保存型编辑/配置表单继续显式标注
(必填)/(选填)。 - 必填字段同时展示明显红色星号;标准
el-form-item统一挂到brick-required-form,自定义标签行统一使用console-required-label。 - 同一个字段不要同时渲染两套必填星号;挂了
brick-required-form的字段不再额外叠加本地星号,用了console-required-label的标签行也不要再叠加required的默认星号。 - 点击保存前先调用
validateBrickRequiredFields(...),不要等后端报错后再告诉用户哪一项为空。 - 保存成功/失败优先用
showBrickStatus(...),不要把短暂提示渲染在表格、按钮或抽屉底部下方。
主题
稳定渲染主题名为 blue、orange、guard、green、night。createBrickConsoleThemePresets() 会暴露 label、mode、description 和 CSS token,其中 blue 是默认浅色主题,night 是全暗主题,orange、guard、green 是深色侧栏加浅色内容区的品牌主题。用户偏好还支持 system,表示跟随系统外观;它不是 CSS token,运行时会通过 resolveBrickConsoleAppearanceTheme() 解析为 blue 或 night。
BrickConsoleShell 默认通过 BrickUserMenu 的头像下拉入口打开标准 BrickAppearanceSettingsDialog 个性化设置弹窗,弹窗提供主题色、语义说明、字号、密度、登录后是否自动全屏(默认否)和语言。BrickAppearanceSwitcher 是特殊布局下的紧凑切换控件,两者共享 createBrickConsoleThemePresets() 的主题预设。业务应用在 shell 根节点设置 data-theme、data-density、data-font-size 后,模块页面和 Element Plus 会通过 CSS token 级联生效;语言偏好由业务壳绑定 ElConfigProvider 与 document.documentElement.lang。
字号阶梯固定为 normal、large、xlarge。normal 保持 14px 基线;large 提升到 16px;xlarge 是适老档,正文基线提升到 18px,并同步增大控件高度和表格行高。业务页面不要在局部覆盖这三个档位,应继续使用 --console-body-size、--console-label-size、--console-caption-size 和 --console-control-height。
theme.css 会把 Buck token 联动到 Element Plus 的常用变量,包括按钮状态色、文本色、边框、ElCard、ElTable、表头、行背景、hover、空态和 overlay。业务页面仍应优先使用 --console-* token,不要在页面里为暗色主题再补一套局部 CSS。
主题、密度和字号的本地偏好持久化也应复用正式 helper,不要在业务壳或验证壳自行写 localStorage key 或 matchMedia 监听:
import {
createBrickConsoleAppearanceRuntime,
readBrickConsoleAppearancePreference,
writeBrickConsoleAppearancePreference,
} from '@wildbuck/core-ui-frontend/appearance';readBrickConsoleAppearancePreference() 会兼容历史 brick-governance-foundation:* key 并统一归一化为 Buck 正式偏好值;writeBrickConsoleAppearancePreference() 只写正式 brick-console:* key。业务壳选择 system 时,应使用轻量 @wildbuck/core-ui-frontend/appearance 子入口里的 createBrickConsoleAppearanceRuntime() 读取 resolvedTheme,把 resolvedTheme 挂到 data-theme,把原始偏好值传给设置入口或保存逻辑。@wildbuck/core-ui-frontend/theme 仍保留完整主题预设导出,适合设置弹窗、主题列表和文档展示使用。
顶部栏与抽屉
BrickConsoleShell 保留 topbar-title、topbar-subtitle、topbar-breadcrumbs、topbar-title slot 和 topbar-primary slot 作为兼容性扩展点;标准业务壳默认不要配置顶部栏左侧内容,更不要拆开 Shell 重写顶部栏。
顶部栏属于全局操作区,默认不展示系统名称、环境说明、当前打开菜单标题、菜单分组或页面说明。系统身份放侧栏品牌区;菜单检索放侧栏菜单上方;页面上下文由侧栏 active 状态和模块页面自己的标题区表达。顶部栏只保留刷新、帮助、通知、当前主体头像下拉等全局操作入口。
如果业务壳希望在顶部栏提供统一刷新入口,应直接复用 BrickConsoleShell 的正式 props,而不是在验证壳、页面或 slot 里手写一个刷新按钮:
<BrickConsoleShell
:refresh-enabled="true"
@refresh="refreshCurrentView"
/>说明:
refresh-enabled打开顶部栏“刷新当前页”按钮。@refresh只表达全局壳动作;具体刷新什么、是否重新加载当前主体、是否重新拉取列表,都由业务壳或模块页面自己决定。- 刷新后的成功/失败提示优先复用
showBrickStatus(...),不要在单个壳里再包一层私有 toast 组件或把提示文案挂在按钮旁边。
如果业务壳希望统一提供浏览器全屏能力,应直接复用 BrickConsoleShell 的正式 props,而不是在页面或验证壳里自行调用 requestFullscreen():
<BrickConsoleShell
:fullscreen-enabled="true"
:fullscreen-auto-enter="appearance.fullscreenAutoEnter"
:locale="appearance.locale"
@update:fullscreen-auto-enter="(value) => appearanceRuntime.setAppearance({ fullscreenAutoEnter: value })"
@update:locale="(value) => appearanceRuntime.setAppearance({ locale: value })"
/>说明:
fullscreen-enabled打开顶部栏“进入全屏 / 退出全屏”按钮。fullscreen-auto-enter读取用户个性化偏好;默认false(不自动进入)。用户可在「个性化设置」中开启“登录后尝试进入”。locale为用户语言偏好(zh-CN/en-US),由业务壳同步到 Element Plus locale 与页面lang。- 浏览器 Fullscreen API 仍受用户手势和浏览器安全策略限制;如果自动尝试被拦截,用户可继续使用顶部栏按钮手动进入全屏。
<BrickConsoleShell
brand-title="统一人脸服务"
brand-subtitle="生产环境"
/>列表页的创建、编辑和详情侧边抽屉优先使用 BrickConsoleDrawer。它统一标题区、正文区、底部操作区、加载态、尺寸和主题 token;短确认仍使用 ElDialog。
<BrickConsoleDrawer
v-model="drawerVisible"
title="组织接入详情"
eyebrow="OpenAPI 接入"
description="维护组织 clientId、授权动作和业务状态。"
>
<slot />
<template #footer>
<el-button @click="drawerVisible = false">取消</el-button>
<el-button type="primary">保存</el-button>
</template>
</BrickConsoleDrawer>侧栏折叠与菜单图标
BrickConsoleShell 和 BrickConsoleSidebar 提供正式侧栏折叠能力:
<BrickConsoleShell
v-model:sidebar-collapsed="sidebarCollapsed"
v-model:sidebar-collapsed-group-keys="collapsedGroupKeys"
:sidebar-collapsible="true"
:sidebar-group-collapsible="true"
brand-mark="B"
:navigation-groups="navigationGroups"
/>折叠态只改变壳层布局和菜单展示密度,不改变导航来源。业务壳仍应通过 navigationGroups 传入 route metadata 与权限过滤后的导航分组(IAM 场景用菜单投影 helper 合并当前主体菜单)。
菜单图标优先级
侧栏 mark 的产品契约如下,不可颠倒:
- 菜单上传图
route.iconUrl(IAM 菜单管理iconResourceId经工作区解析) - 业务组件
route.icon(Vue 组件) - 线图标兜底
BrickConsoleNavIcon:显式iconName/ 字符串icon,否则resolveBrickConsoleNavIconName(route)按 id/path 推断,最后通用menu
线图标只是无上传图时的正式占位,不替代菜单管理上传。abbr / iconText 可用于搜索与辅助文案,不是默认主视觉。
默认折叠控件在侧栏底部,由 BrickConsoleSidebarCollapseToggle 提供:双箭头 +「折叠侧边栏」/「展开侧边栏」,无底板。不要在 Shell 与 Sidebar 各维护一份折叠按钮。
菜单快速检索使用 sidebar-searchable;搜索会匹配菜单标题、路径、分组和 route 的 keywords/searchKeywords 以及 abbr/iconText/shortTitle/collapsedTitle。复杂 logo、额外筛选、折叠按钮或图标渲染可以通过 sidebar-brand-mark、sidebar-nav-before、sidebar-collapse-toggle、sidebar-route-icon slot 扩展,不需要复制 BrickConsoleSidebar。
自动化、Playwright 冒烟和调试脚本如果需要稳定定位某个菜单入口,应使用侧栏路由按钮上的 data-route-id="<route.id>",不要依赖可变的菜单名称、文案或分组标题做选择器。
菜单分组折叠同样由 BrickConsoleShell 承载:分组标题默认可点击折叠,navigationGroups 中的分组可设置 collapsible: false 禁止折叠,或设置 defaultCollapsed: true 默认折叠。需要受控状态时使用 v-model:sidebar-collapsed-group-keys;当前激活路由所在分组会自动展开,避免折叠后隐藏当前页面入口。
右侧上下文顶栏
右侧 context panel(如 AI 助手)顶栏应使用 BrickConsoleContextHeader(样式类 .shell-context-header),高度与主顶栏对齐:var(--shell-topbar-height, 48px),底边与背景 token 与 topbar 一致。顶栏内图标按钮复用 .shell-icon-button。
如果业务壳需要持久化分组折叠状态或在模块页面里发起“跳转到某个管理页面”的正式壳导航意图,应复用 shell-navigation 的 helper,而不是自己约定事件名或存储 key:
import {
dispatchBrickConsoleManagementIntent,
subscribeBrickConsoleManagementIntent,
readBrickConsoleCollapsedGroupKeys,
writeBrickConsoleCollapsedGroupKeys,
resolveBrickConsoleNavIconName,
} from '@wildbuck/core-ui-frontend/shell';