Skip to content

feat: 自定义皮肤/主题支持#3003

Open
thedavidweng wants to merge 1 commit into
Wei-Shaw:mainfrom
thedavidweng:feat/theme-system
Open

feat: 自定义皮肤/主题支持#3003
thedavidweng wants to merge 1 commit into
Wei-Shaw:mainfrom
thedavidweng:feat/theme-system

Conversation

@thedavidweng
Copy link
Copy Markdown

概述

为 sub2api 添加主题系统,允许管理员通过安装自定义主题来修改前端界面样式,而不影响任何业务功能。

Closes #2996

功能特性

主题安装

  • ZIP 上传:管理后台拖拽或选择 .zip 文件安装
  • GitHub 导入:输入仓库 URL,自动拉取 main/master 分支安装

主题管理

  • 管理后台新增「主题」设置页(位于「功能开关」和「安全认证」之间)
  • 支持激活、取消激活、删除主题
  • 支持主题自定义配置项(颜色选择器、文本输入、下拉选择等)

主题格式

theme.zip
  sub2api-theme.json    # 元数据 + 配置项声明
  style.css             # 主 CSS,覆盖设计令牌和组件样式
  preview.png           # 可选预览图
  fonts/ images/        # 可选资源

CSS 注入机制

  • 激活主题的 CSS 通过 <link> 注入到 index.html</head>
  • 主题配置转为 --theme-* CSS 自定义属性通过 <style> 块注入
  • 无主题时行为完全不变

改动文件

文件 说明
backend/internal/service/theme_service.go 主题服务(安装、激活、删除、配置、CSS 消毒)
backend/internal/handler/admin/theme_handler.go Admin API handler(9 个端点)
backend/internal/handler/theme_asset_handler.go 公开资源服务(无需认证)
backend/internal/server/routes/theme.go 公开路由注册
backend/internal/web/embed_on.go CSS 注入 + bypass 规则
backend/internal/web/embed_off.go 非 embed 构建 stub
backend/internal/web/embed_test.go 测试适配新签名
backend/internal/handler/handler.go AdminHandlers 添加 Theme 字段
backend/internal/handler/wire.go Wire 依赖注入更新
backend/internal/service/wire.go Wire 依赖注入更新
backend/internal/server/http.go ProvideRouter 添加 themeService 参数
backend/internal/server/router.go SetupRouter 接入 ThemeService
backend/internal/server/routes/admin.go 注册 theme 管理路由
backend/cmd/server/wire_gen.go Wire 生成代码更新
frontend/src/api/admin/themes.ts 前端 API 客户端
frontend/src/api/admin/index.ts barrel export 更新
frontend/src/components/admin/ThemeManager.vue 主题管理 UI 组件
frontend/src/components/icons/Icon.vue 添加 paintBrush 图标
frontend/src/views/admin/SettingsView.vue 添加 theme tab
frontend/src/i18n/locales/zh.ts 中文翻译
frontend/src/i18n/locales/en.ts 英文翻译

安全措施

  • CSS 消毒:移除 expression()-moz-bindingbehavior、外部 url()javascript: 等危险构造
  • 文件类型白名单:.css, .woff, .woff2, .png, .svg
  • 大小限制:ZIP 10MB、单 CSS 512KB、总解压 20MB
  • 路径遍历防护:short ID 正则 ^[a-z0-9][a-z0-9_-]{0,31}$ + filepath.Clean + 前缀检查

测试

  • ZIP 上传安装主题
  • GitHub URL 安装主题
  • 激活/取消激活主题
  • 删除主题
  • 主题配置项编辑保存
  • 无主题时默认行为不变
  • CSS 消毒(尝试上传含危险 CSS 的主题)

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 3, 2026

All contributors have signed the CLA. ✅
Posted by the CLA Assistant Lite bot.

@thedavidweng
Copy link
Copy Markdown
Author

I have read the CLA Document and I hereby sign the CLA

Allow admins to install and activate themes to customize the sub2api
frontend appearance via CSS overrides. Themes are distributed as zip
packages or imported from GitHub repositories, similar to Komari Monitor.

Backend:
- Add ThemeService for theme lifecycle management (install, activate,
  delete, config) with CSS sanitization and path traversal protection
- Add admin API endpoints under /api/v1/admin/themes for CRUD operations
- Add public /api/v1/themes/assets route for serving theme static files
- Inject theme CSS <link> and config CSS variables into index.html
  before </head> alongside existing window.__APP_CONFIG__ injection
- Wire ThemeService into FrontendServer with cache invalidation callback

Frontend:
- Add ThemeManager component with drag-drop zip upload, GitHub URL
  install, theme grid, config editor, and delete confirmation
- Add 'Theme' tab to admin settings page between Features and Security
- Add i18n translations for zh and en locales

Theme package format:
- sub2api-theme.json: metadata (name, short, version, author) + config schema
- style.css: main CSS file that overrides design tokens and component styles
- Optional: preview.png, fonts/, images/, additional CSS files

Security measures:
- CSS sanitization (strip expression(), -moz-binding, external url())
- File type whitelist (.css, .woff2, .png, .svg, etc.)
- Size limits (10MB zip, 512KB CSS, 20MB total extracted)
- Path traversal prevention via short ID validation + filepath.Clean
github-actions Bot added a commit that referenced this pull request Jun 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: 自定义皮肤/主题支持

1 participant