完整界面主题包
入口:设置 → 外观(/console/settings?tab=appearance),完整主题选择、明暗偏好与顶部栏自定义集中在同一页。主题在当前浏览器生效,明暗模式继续使用原来的独立开关。旧的 /console/store?tab=themes 链接自动跳转到外观设置。
两套界面
| 经典控制台 | 现代工作空间 | |
|---|---|---|
| 导航 | 原版顶部横向导航、运行状态与命令入口 | 分组侧栏、独立页头、可收起导航 |
| 连接 | 目录与常驻详情并排;窄屏上下排列 | 完整宽度目录;按需打开详情抽屉 |
| 模型 | 较宽目录显示更多列,与配置区并排 | 紧凑目录、宽配置区、次要信息逐级展开 |
| 排版与控件 | 蓝金色、直角、较强的边线和等宽标注 | 纸白/石墨、蓝色主操作、柔和表面与更多留白 |
| 主动重播 | 原版机械门与控制台字排 | 双行品牌字排、斜切揭幕 |
| 手机 | 收起顶部导航,使用导航抽屉 | 收起侧栏,使用导航抽屉 |
经典样式来自仓库提交 72179f3063c4b9a529103b602c8833b15426bc46 的前端快照。保留原版视觉和主要布局,同时继续使用当前的业务功能、鉴权、表单与无障碍修复;没有恢复已修复的旧业务代码。
包结构与边界
web/src/themes/types.ts 定义版本化的 UIThemePackage,registry.ts 注册可用主题。每个包提供:
id、version、apiVersion与双语名称/介绍键。Chrome:导航、页头、全局操作的独立 React 组件。Details:业务详情的布局组件;经典包使用常驻侧面板,现代包使用抽屉。Entrance:主动重播使用的品牌画面;计时器、跳过、焦点与减少动态效果由公共宿主负责。日常登录立即建立会话、短暂淡入,退出立即断开会话。- 独立样式入口。经典包的全部选择器限定在
:root[data-appearance="classic"],动画名称带classic-前缀;compat.css处理当前业务组件与旧版布局的结合。现代包入口统一组合现有样式模块。
业务页面通过稳定的 ConsoleShell 内容容器渲染。切换包只替换导航与展示组件,公共内容容器、当前路由、表单状态和会话不会因为更换导航组件而整体卸载。渠道、路由、透传、计费、图像协议与插件服务不由主题控制。
appearance.tsx 管理界面包与明暗两个独立偏好。未选择时默认经典包;未设置明暗时默认浅色,已有 meta-gateway.theme 值继续保留。无效包 ID 回退到经典包,浏览器存储不可用时仍能在当前会话应用主题;其他标签页改变偏好时同步更新。
扩展方式
新增包放进 web/src/themes/<id>/,实现上述展示接口,添加 UIThemeId、注册包和样式入口,补齐 zh/en 介绍,再执行前端与 Go 质量门。外观设置中的主题列表从注册表产生。
当前是内置的前端主题包:可以在外观设置中直接切换,随 MG 构建分发。现有 sidecar 功能插件继续采用原有服务协议。当前没有远程下载/安装第三方主题、执行远程 JSX 或新增主题上传端点;未来的安装器需要另行定义包格式、资源加载与版本兼容,不能把后端 sidecar 地址当作前端代码入口。
开发约定
- 主题与明暗必须互相独立;未知主题回退到经典包;浏览器存储不可用时仍能在当前会话应用主题;多标签页之间同步。
- 完整导航更换后,业务内容只能挂载一次,未保存的输入不能丢。
- 两套手机导航在选中目的地后都要关闭。
- 改动任一主题后都必须重新构建
internal/webui/dist,再编译 Go。主题切换本身不触发任何后端写入。
两套完整样式目前合并分发。引入更多主题时应改为按包加载,避免所有包一起增长。