diff --git a/.workbuddy/memory/2026-10-19.md b/.workbuddy/memory/2026-10-19.md index b3f2001..bc87fa3 100644 --- a/.workbuddy/memory/2026-10-19.md +++ b/.workbuddy/memory/2026-10-19.md @@ -385,3 +385,24 @@ P1 剩余两项(首屏跟随系统深色、首页 Waline 懒加载)用户明 3. `writePreview` 用全文搜 `data-theme="dark"` 判断是否已加属性 → 命中内联主题 css 里的选择器,深色预览没生效; 改为只看 `` 开标签。 4. 脚本改 form/user.go 时把插入块写在结构体中间,拼出 `} Language ...`;靠 Read 复查发现并重写。 + +## 主题 follow-up(部署后反馈两处) + +1. **/user/* 不生效主题**:根因是 `ctx.Data["ThemeSlug"]` 只在 `question.Pager`(`/_/{domain}`)里注入, + `/user/*` 完全没走这条链路。修法:`internal/context/context.go` 的 Contexter 里按 + `isThemeScope(path) && c.IsLogged` 注入 `theme.Resolve(c.User.Theme)`; + `isThemeScope` 只认 `/user` 与 `/user/`(不能用裸 `HasPrefix("/user")`,会误吞 `/username`)。 + 新增 `internal/context/context_test.go` 守住路径白名单;page.go 的注释同步改。 + 公开页(`/`、`/explore`、`/vote/{token}`)**仍不跟随**登录用户主题,保持站点默认。 + +2. **sakura 显示奇怪**(用户选择:顶栏白与粉底割裂 / 卡片纯白太突 / 底色分布不均): + - base.css 新增令牌 `--tb-navbar`(`:root` 里 `var(--tb-surface)`,亮暗两条 navbar 规则都改成 + `var(--tb-navbar, var(--tb-surface))`),主题可单独给顶栏上色。 + - sakura v2:底色改**纯色** `#fceef3`(不用渐变——渐变会被读成"不均匀"), + 顶栏 `#fff6f9`、卡片 `#fffafc`(暖白,不再是纯白硬切),网点从 16px/0.14 放宽到 24px/0.05。 + - 静态版本 `20261019f`;`_scaffold.css` 令牌说明 19→20。 + - `profile.theme.hint` 四语言文案改成「提问箱页面 + 本人后台生效,公开页保持默认」。 + - `zz_preview_test.go` 抽出 `inlineThemeCSS()`,并新增 `preview-profile-sakura-*`(后台页面也要在主题下检查)。 + +验证:`go build ./...`(须带 webp overlay)、i18n/theme/context/templates 四个包测试全绿。 +渲染法:抓线上 `/_/admin6` HTML → 把 base.css 指到本地新文件、主题 css 内联 → 无头 Chrome `--headless=old` 截图。 diff --git a/.workbuddy/memory/MEMORY.md b/.workbuddy/memory/MEMORY.md index c28f19b..24a1827 100644 --- a/.workbuddy/memory/MEMORY.md +++ b/.workbuddy/memory/MEMORY.md @@ -153,3 +153,17 @@ `reports --domain|--email [--days]`(证据包)、`--pending`、`--stats --days N`(Top 被举报箱主 + Top 举报 IP); `hide-public [--only-reported] [--since N]`。 - 本地冒烟:`NEKOBOX_CONFIG_PATH=`;`conf.Init` 强制 `app.external_url`、`server.salt`、`server.xsrf_key` 非空。 + +## 主题(箱主个性化) + +- 两个注入点,别再漏:`/_/{domain}/*` → `question.Pager` 按 `pageUser.Theme`; + `/user/*` → `internal/context` 的 Contexter 按 `c.User.Theme`(`isThemeScope()` 只认 `/user` 与 `/user/`)。 + 公开页(`/`、`/explore`、`/vote/{token}`)不跟随登录用户主题。 +- 主题 = 一个 css 文件只覆盖令牌;新增主题不用改 Go/模板,放 `static/css/themes/.css` + + `[theme] available` 登记即可(`static/fs.go` 已嵌整个目录)。底稿 `_scaffold.css`。 +- **必须同时写浅色块与深色块**(`html[data-theme-style=x]` / `html[data-theme="dark"][data-theme-style=x]`), + `TestThemeCSSComplete` 会查;色块预览由浅色块的 `--tb-bg` + `--tb-primary` 自动生成(色值过正则防注入)。 +- 令牌 `--tb-navbar`:顶栏底色,默认 `var(--tb-surface)`。页面底色偏彩时主题应覆盖它, + 否则顶栏是纯白带、压在彩底上割裂(用户实测反馈过)。 +- 主题底色用**纯色**,别用整页渐变——会被读成「底色分布不均匀」;图案建议 ≥24px、透明度 ≤0.06。 +- 改了 base.css / 主题 css 必须 +1 `conf.StaticVersion`(两者共用同一个 v)。 diff --git a/internal/conf/static.go b/internal/conf/static.go index 7e9ad88..d57287f 100644 --- a/internal/conf/static.go +++ b/internal/conf/static.go @@ -10,7 +10,7 @@ var ( BuildCommit = "dev" // StaticVersion 静态资源缓存版本号:base.css 与主题 css 共用,改样式只改这一处。 - StaticVersion = "20261019e" + StaticVersion = "20261019f" ) // 文本审核通道取值([security] text_censor_source)。定义在 conf 侧, diff --git a/internal/context/context.go b/internal/context/context.go index 4b65648..89cefa7 100644 --- a/internal/context/context.go +++ b/internal/context/context.go @@ -26,6 +26,7 @@ import ( "github.com/tamakyi/TamaBox/internal/i18n" "github.com/tamakyi/TamaBox/internal/shared" templatepkg "github.com/tamakyi/TamaBox/internal/template" + "github.com/tamakyi/TamaBox/internal/theme" ) type EndpointType string @@ -239,6 +240,13 @@ func Contexter() flamego.Handler { isUserPage := strings.HasPrefix(path, "/user") || strings.HasPrefix(path, "/_/") c.Data["IsUserPage"] = isUserPage + // 主题:/user 后台是箱主本人的页面,跟随本人配置; + // /_/{domain} 的箱主主题由 question.Pager 覆盖(访客看到的是箱主的选择)。 + // 空串(未选且站点无默认主题)= 不加载主题 css。 + if isThemeScope(path) && c.IsLogged { + c.Data["ThemeSlug"] = theme.Resolve(c.User.Theme) + } + // SEO:仅公开页(首页/注册/登录/explore)允许被搜索引擎收录; // 提问内容(提问箱页、单题页)、密码页、私信、用户后台等隐私页一律 noindex。 isPublicPage := path == "/" || path == "/register" || path == "/login" || strings.HasPrefix(path, "/explore") @@ -327,3 +335,10 @@ func (c *Context) Lang() string { } return i18n.Default } + +// isThemeScope 判断该路径的主题是否由「当前登录用户自己的配置」决定。 +// 只覆盖 /user 后台(本人页面);提问箱相关页面由 question.Pager 按箱主注入, +// 公开页(首页/探索/登录)保持站点默认外观,不跟随登录状态变化。 +func isThemeScope(path string) bool { + return path == "/user" || strings.HasPrefix(path, "/user/") +} diff --git a/internal/context/context_test.go b/internal/context/context_test.go new file mode 100644 index 0000000..1c25dff --- /dev/null +++ b/internal/context/context_test.go @@ -0,0 +1,30 @@ +package context + +import "testing" + +// 主题作用域:/user 后台必须命中(否则设置页、题目管理页拿不到自己的主题), +// 其余路径不得命中(提问箱页面由 question.Pager 按箱主注入,公开页保持站点默认)。 +func TestIsThemeScope(t *testing.T) { + cases := map[string]bool{ + "/user": true, + "/user/": true, + "/user/profile": true, + "/user/questions": true, + "/user/votes/1/results": true, + "/username": false, // 前缀相近但不是用户后台 + "/_/admin6": false, + "/_/admin6/share-card": false, + "/": false, + "/explore": false, + "/vote/abc": false, + "/api/v1/user/admin6": false, + "/api/v1/user": false, + "/deactivated": false, + } + + for path, want := range cases { + if got := isThemeScope(path); got != want { + t.Errorf("isThemeScope(%q) = %v, want %v", path, got, want) + } + } +} diff --git a/internal/i18n/dict_en.go b/internal/i18n/dict_en.go index 12b5238..86e4ffd 100644 --- a/internal/i18n/dict_en.go +++ b/internal/i18n/dict_en.go @@ -933,7 +933,7 @@ var enDict = map[string]string{ // 主题:设置页选择器与主题显示名(theme.name. 由 internal/theme 约定) "profile.theme.title": "Theme", - "profile.theme.hint": "Applies to your question box pages only; the rest of the site keeps the default look.", + "profile.theme.hint": "Applies to your question box pages and your dashboard; public pages (home, explore) keep the default look.", "profile.theme.followDefault": "Follow site default", "profile.theme.save": "Save theme", "profile.theme.saved": "Theme saved", diff --git a/internal/i18n/dict_ja.go b/internal/i18n/dict_ja.go index 1cc7c02..8064eb1 100644 --- a/internal/i18n/dict_ja.go +++ b/internal/i18n/dict_ja.go @@ -933,7 +933,7 @@ var jaDict = map[string]string{ // 主题:设置页选择器与主题显示名(theme.name. 由 internal/theme 约定) "profile.theme.title": "テーマ", - "profile.theme.hint": "質問箱のページにのみ適用されます。他のページは既定の外観のままです。", + "profile.theme.hint": "質問箱のページと管理画面に適用されます。ホーム・探索などの公開ページは既定の外観のままです。", "profile.theme.followDefault": "サイト既定に従う", "profile.theme.save": "テーマを保存", "profile.theme.saved": "テーマを保存しました", diff --git a/internal/i18n/dict_zh_cn.go b/internal/i18n/dict_zh_cn.go index 26b7fa6..a823b78 100644 --- a/internal/i18n/dict_zh_cn.go +++ b/internal/i18n/dict_zh_cn.go @@ -874,7 +874,7 @@ var zhCNDict = map[string]string{ // 主题:设置页选择器与主题显示名(theme.name. 由 internal/theme 约定) "profile.theme.title": "主题外观", - "profile.theme.hint": "仅对提问箱页面生效,站内其它页面保持默认外观。", + "profile.theme.hint": "对提问箱页面和你的后台页面生效,首页/探索等公开页保持默认外观。", "profile.theme.followDefault": "跟随站点默认", "profile.theme.save": "保存主题", "profile.theme.saved": "主题已保存", diff --git a/internal/i18n/dict_zh_tw.go b/internal/i18n/dict_zh_tw.go index 9f4a069..789bbfa 100644 --- a/internal/i18n/dict_zh_tw.go +++ b/internal/i18n/dict_zh_tw.go @@ -933,7 +933,7 @@ var zhTWDict = map[string]string{ // 主题:设置页选择器与主题显示名(theme.name. 由 internal/theme 约定) "profile.theme.title": "主題外觀", - "profile.theme.hint": "僅對提問箱頁面生效,站內其他頁面維持預設外觀。", + "profile.theme.hint": "對提問箱頁面與你的後台頁面生效,首頁/探索等公開頁維持預設外觀。", "profile.theme.followDefault": "跟隨站點預設", "profile.theme.save": "儲存主題", "profile.theme.saved": "主題已儲存", diff --git a/outputs/cmp-default.png b/outputs/cmp-default.png new file mode 100644 index 0000000..0f7c092 Binary files /dev/null and b/outputs/cmp-default.png differ diff --git a/outputs/cmp-sakura-mobile.png b/outputs/cmp-sakura-mobile.png new file mode 100644 index 0000000..d7a431e Binary files /dev/null and b/outputs/cmp-sakura-mobile.png differ diff --git a/outputs/cmp-sakura.png b/outputs/cmp-sakura.png new file mode 100644 index 0000000..0e04d9e Binary files /dev/null and b/outputs/cmp-sakura.png differ diff --git a/outputs/crop-profile-bottom.png b/outputs/crop-profile-bottom.png new file mode 100644 index 0000000..7552be4 Binary files /dev/null and b/outputs/crop-profile-bottom.png differ diff --git a/outputs/crop-sakura-footer.png b/outputs/crop-sakura-footer.png new file mode 100644 index 0000000..cf61f6f Binary files /dev/null and b/outputs/crop-sakura-footer.png differ diff --git a/outputs/crop-sakura-form.png b/outputs/crop-sakura-form.png new file mode 100644 index 0000000..c171050 Binary files /dev/null and b/outputs/crop-sakura-form.png differ diff --git a/outputs/crop-sakura-pattern.png b/outputs/crop-sakura-pattern.png new file mode 100644 index 0000000..bddfab1 Binary files /dev/null and b/outputs/crop-sakura-pattern.png differ diff --git a/outputs/live-admin6.html b/outputs/live-admin6.html new file mode 100644 index 0000000..67f3377 --- /dev/null +++ b/outputs/live-admin6.html @@ -0,0 +1,1064 @@ + + + + + + admin6 - 狼的提问箱 | 匿名提问箱 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + + +
+ + + +
+
+

人机验证

+

请计算下方的算术题以验证你不是机器人

+
+ 加载中... + +
+
+ +
+ +
+ + +
+
+
+ + + + + + + + + + +
+
+
+ +

admin6

+

问你想问的

+
+ + + + + + + bloglink + + +
+
+
+
+ +
+
+ + + + +
+ + +

扫码向@admin6提问
谁都可以以匿名的形式提问

+ + + + + + + + + + + + + + + + + + +
+ + + + +
+ +
+ +
+ + + + + + + +
+ +
+
+ + + +
+ +
+
+ +
+ + + +
+ +
+
+
+ + + +
+ +
+ +
+ +
+
+
+ + + + + + +
+ + +
+
+ +

+
+ 社区规则 | + + 找站长 +
+ 盘 + | 公告板 + | 聊天室 + | 监控板 + | 导航页 +
Powered by NekoBox | 狼ICP备 20230101 +
提问箱已成功存活: +

+ + +
+
+ + + + diff --git a/outputs/live-default.html b/outputs/live-default.html new file mode 100644 index 0000000..ac7c4f2 --- /dev/null +++ b/outputs/live-default.html @@ -0,0 +1,1064 @@ + + + + + + admin6 - 狼的提问箱 | 匿名提问箱 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + + +
+ + + +
+
+

人机验证

+

请计算下方的算术题以验证你不是机器人

+
+ 加载中... + +
+
+ +
+ +
+ + +
+
+
+ + + + + + + + + + +
+
+
+ +

admin6

+

问你想问的

+
+ + + + + + + bloglink + + +
+
+
+
+ +
+
+ + + + +
+ + +

扫码向@admin6提问
谁都可以以匿名的形式提问

+ + + + + + + + + + + + + + + + + + +
+ + + + +
+ +
+ +
+ + + + + + + +
+ +
+
+ + + +
+ +
+
+ +
+ + + +
+ +
+
+
+ + + +
+ +
+ +
+ +
+
+
+ + + + + + +
+ + +
+
+ +

+
+ 社区规则 | + + 找站长 +
+ 盘 + | 公告板 + | 聊天室 + | 监控板 + | 导航页 +
Powered by NekoBox | 狼ICP备 20230101 +
提问箱已成功存活: +

+ + +
+
+ + + + diff --git a/outputs/live-sakura-1280.png b/outputs/live-sakura-1280.png new file mode 100644 index 0000000..1e4ceb3 Binary files /dev/null and b/outputs/live-sakura-1280.png differ diff --git a/outputs/live-sakura-dark.html b/outputs/live-sakura-dark.html new file mode 100644 index 0000000..5c86a60 --- /dev/null +++ b/outputs/live-sakura-dark.html @@ -0,0 +1,1064 @@ + + + + + + admin6 - 狼的提问箱 | 匿名提问箱 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + + +
+ + + +
+
+

人机验证

+

请计算下方的算术题以验证你不是机器人

+
+ 加载中... + +
+
+ +
+ +
+ + +
+
+
+ + + + + + + + + + +
+
+
+ +

admin6

+

问你想问的

+
+ + + + + + + bloglink + + +
+
+
+
+ +
+
+ + + + +
+ + +

扫码向@admin6提问
谁都可以以匿名的形式提问

+ + + + + + + + + + + + + + + + + + +
+ + + + +
+ +
+ +
+ + + + + + + +
+ +
+
+ + + +
+ +
+
+ +
+ + + +
+ +
+
+
+ + + +
+ +
+ +
+ +
+
+
+ + + + + + +
+ + +
+
+ +

+
+ 社区规则 | + + 找站长 +
+ 盘 + | 公告板 + | 聊天室 + | 监控板 + | 导航页 +
Powered by NekoBox | 狼ICP备 20230101 +
提问箱已成功存活: +

+ + +
+
+ + + + diff --git a/outputs/live-sakura-dark.png b/outputs/live-sakura-dark.png new file mode 100644 index 0000000..652fb1c Binary files /dev/null and b/outputs/live-sakura-dark.png differ diff --git a/outputs/live-sakura.html b/outputs/live-sakura.html new file mode 100644 index 0000000..265710d --- /dev/null +++ b/outputs/live-sakura.html @@ -0,0 +1,1064 @@ + + + + + + admin6 - 狼的提问箱 | 匿名提问箱 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + + +
+ + + +
+
+

人机验证

+

请计算下方的算术题以验证你不是机器人

+
+ 加载中... + +
+
+ +
+ +
+ + +
+
+
+ + + + + + + + + + +
+
+
+ +

admin6

+

问你想问的

+
+ + + + + + + bloglink + + +
+
+
+
+ +
+
+ + + + +
+ + +

扫码向@admin6提问
谁都可以以匿名的形式提问

+ + + + + + + + + + + + + + + + + + +
+ + + + +
+ +
+ +
+ + + + + + + +
+ +
+
+ + + +
+ +
+
+ +
+ + + +
+ +
+
+
+ + + +
+ +
+ +
+ +
+
+
+ + + + + + +
+ + +
+
+ +

+
+ 社区规则 | + + 找站长 +
+ 盘 + | 公告板 + | 聊天室 + | 监控板 + | 导航页 +
Powered by NekoBox | 狼ICP备 20230101 +
提问箱已成功存活: +

+ + +
+
+ + + + diff --git a/outputs/new-default.html b/outputs/new-default.html new file mode 100644 index 0000000..ec62a58 --- /dev/null +++ b/outputs/new-default.html @@ -0,0 +1,1064 @@ + + + + + + admin6 - 狼的提问箱 | 匿名提问箱 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + + +
+ + + +
+
+

人机验证

+

请计算下方的算术题以验证你不是机器人

+
+ 加载中... + +
+
+ +
+ +
+ + +
+
+
+ + + + + + + + + + +
+
+
+ +

admin6

+

问你想问的

+
+ + + + + + + bloglink + + +
+
+
+
+ +
+
+ + + + +
+ + +

扫码向@admin6提问
谁都可以以匿名的形式提问

+ + + + + + + + + + + + + + + + + + +
+ + + + +
+ +
+ +
+ + + + + + + +
+ +
+
+ + + +
+ +
+
+ +
+ + + +
+ +
+
+
+ + + +
+ +
+ +
+ +
+
+
+ + + + + + +
+ + +
+
+ +

+
+ 社区规则 | + + 找站长 +
+ 盘 + | 公告板 + | 聊天室 + | 监控板 + | 导航页 +
Powered by NekoBox | 狼ICP备 20230101 +
提问箱已成功存活: +

+ + +
+
+ + + + diff --git a/outputs/new-sakura-dark.html b/outputs/new-sakura-dark.html new file mode 100644 index 0000000..956f090 --- /dev/null +++ b/outputs/new-sakura-dark.html @@ -0,0 +1,1114 @@ + + + + + + admin6 - 狼的提问箱 | 匿名提问箱 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + + +
+ + + +
+
+

人机验证

+

请计算下方的算术题以验证你不是机器人

+
+ 加载中... + +
+
+ +
+ +
+ + +
+
+
+ + + + + + + + + + +
+
+
+ +

admin6

+

问你想问的

+
+ + + + + + + bloglink + + +
+
+
+
+ +
+
+ + + + +
+ + +

扫码向@admin6提问
谁都可以以匿名的形式提问

+ + + + + + + + + + + + + + + + + + +
+ + + + +
+ +
+ +
+ + + + + + + +
+ +
+
+ + + +
+ +
+
+ +
+ + + +
+ +
+
+
+ + + +
+ +
+ +
+ +
+
+
+ + + + + + +
+ + +
+
+ +

+
+ 社区规则 | + + 找站长 +
+ 盘 + | 公告板 + | 聊天室 + | 监控板 + | 导航页 +
Powered by NekoBox | 狼ICP备 20230101 +
提问箱已成功存活: +

+ + +
+
+ + + + diff --git a/outputs/new-sakura-light.html b/outputs/new-sakura-light.html new file mode 100644 index 0000000..9e54807 --- /dev/null +++ b/outputs/new-sakura-light.html @@ -0,0 +1,1114 @@ + + + + + + admin6 - 狼的提问箱 | 匿名提问箱 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + + +
+ + + +
+
+

人机验证

+

请计算下方的算术题以验证你不是机器人

+
+ 加载中... + +
+
+ +
+ +
+ + +
+
+
+ + + + + + + + + + +
+
+
+ +

admin6

+

问你想问的

+
+ + + + + + + bloglink + + +
+
+
+
+ +
+
+ + + + +
+ + +

扫码向@admin6提问
谁都可以以匿名的形式提问

+ + + + + + + + + + + + + + + + + + +
+ + + + +
+ +
+ +
+ + + + + + + +
+ +
+
+ + + +
+ +
+
+ +
+ + + +
+ +
+
+
+ + + +
+ +
+ +
+ +
+
+
+ + + + + + +
+ + +
+
+ +

+
+ 社区规则 | + + 找站长 +
+ 盘 + | 公告板 + | 聊天室 + | 监控板 + | 导航页 +
Powered by NekoBox | 狼ICP备 20230101 +
提问箱已成功存活: +

+ + +
+
+ + + + diff --git a/outputs/preview-assets/base.css b/outputs/preview-assets/base.css index 0f7c3a1..a18b14e 100644 --- a/outputs/preview-assets/base.css +++ b/outputs/preview-assets/base.css @@ -11,6 +11,8 @@ --tb-surface: #ffffff; --tb-surface-2: #f4f6f8; --tb-surface-hover: #f3f7ff; + /* 顶栏底色:默认跟随卡片面;主题想消除「纯白顶栏压在彩色底上」的割裂时单独覆盖 */ + --tb-navbar: var(--tb-surface); --tb-border: #e8eaee; --tb-text: #1f2329; --tb-text-secondary: #5c6370; @@ -23,6 +25,10 @@ --tb-shadow: 0 1px 2px rgba(16, 24, 40, 0.04), 0 12px 28px -18px rgba(16, 24, 40, 0.20); --tb-shadow-hover: 0 1px 2px rgba(16, 24, 40, 0.05), 0 18px 40px -20px rgba(16, 24, 40, 0.28); --tb-font: system-ui, -apple-system, "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Noto Sans CJK SC", "Microsoft YaHei", sans-serif; + /* 整页背景:主题可覆盖。图案层叠在背景图之上,两者都不用时保持纯色底。 */ + --tb-page-image: none; + --tb-page-pattern: none; + --tb-page-pattern-size: auto; } html[data-theme="dark"] { --tb-bg: #1a1d23; @@ -134,7 +140,7 @@ color: var(--tb-text) !important; } html[data-theme="dark"] .uk-navbar-container { - background-color: var(--tb-surface) !important; + background-color: var(--tb-navbar, var(--tb-surface)) !important; color: var(--tb-text) !important; } html[data-theme="dark"] .uk-navbar-nav > li > a, @@ -239,12 +245,19 @@ html[data-theme="dark"] .explore-intro { color: var(--tb-text-muted) !important; } - /* 切换按钮图标切换 */ + /* 切换按钮图标切换(内联 SVG,不依赖 UIkit 图标库) */ + #theme-toggle .tb-icon-light, #theme-toggle-mobile .tb-icon-light, + #theme-toggle .tb-icon-dark, #theme-toggle-mobile .tb-icon-dark { + display: inline-flex; + align-items: center; + } + #theme-toggle .tb-icon-light svg, #theme-toggle-mobile .tb-icon-light svg, + #theme-toggle .tb-icon-dark svg, #theme-toggle-mobile .tb-icon-dark svg { display: block; } #theme-toggle .tb-icon-dark, #theme-toggle-mobile .tb-icon-dark { display: none; } html[data-theme="dark"] #theme-toggle .tb-icon-light, html[data-theme="dark"] #theme-toggle-mobile .tb-icon-light { display: none; } html[data-theme="dark"] #theme-toggle .tb-icon-dark, - html[data-theme="dark"] #theme-toggle-mobile .tb-icon-dark { display: inline; } + html[data-theme="dark"] #theme-toggle-mobile .tb-icon-dark { display: inline-flex; } /* 基础质感层:只调整外观(圆角/投影/字体/数字对齐),不改任何结构与布局。 颜色一律取自头部令牌,亮暗两套自动生效,因此这里不需要再写 html[data-theme="dark"] 分支。 */ @@ -253,6 +266,12 @@ body { font-family: var(--tb-font); background-color: var(--tb-bg); + /* 主题的整页背景:图案(平铺)在上,图片(cover)在下,都不设置时等价于纯色 */ + background-image: var(--tb-page-pattern, none), var(--tb-page-image, none); + background-size: var(--tb-page-pattern-size, auto), cover; + background-repeat: repeat, no-repeat; + background-position: left top, center center; + background-attachment: scroll, fixed; color: var(--tb-text); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; @@ -306,7 +325,7 @@ box-shadow: var(--tb-shadow); } .uk-navbar-container:not(.uk-navbar-transparent) { - background-color: var(--tb-surface); + background-color: var(--tb-navbar, var(--tb-surface)); } /* 键盘可达性:仅在键盘聚焦时出现描边,鼠标点击不出现 */ .uk-button:focus-visible, @@ -320,6 +339,89 @@ color: var(--tb-text-muted); } +/* 主题选择器(设置页):色块 + 名称。纯展示,不参与主题令牌,所以放在基础层。 */ +.tb-theme-hint { + margin: 0 0 6px; + font-size: 0.8rem; + color: var(--tb-text-muted); +} +.tb-theme-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); + gap: 8px; + margin: 8px 0 2px; +} +.tb-theme-opt { + display: flex; + align-items: center; + gap: 8px; + padding: 7px 9px; + border: 1px solid var(--tb-border); + border-radius: var(--tb-radius-sm); + cursor: pointer; +} +.tb-theme-opt:hover { + background-color: var(--tb-surface-hover); +} +.tb-theme-opt input { + margin: 0; +} +.tb-theme-swatch { + flex: 0 0 auto; + width: 26px; + height: 26px; + border-radius: var(--tb-radius-xs); + border: 1px solid var(--tb-border); + background-color: var(--tb-surface-2); +} +/* 选中态用描边而不是 :has(),兼容老 WebView */ +.tb-theme-opt input:checked + .tb-theme-swatch { + outline: 2px solid var(--tb-primary); + outline-offset: 1px; +} +.tb-theme-name { + font-size: 0.84rem; + line-height: 1.3; +} +.tb-theme-opt input:checked ~ .tb-theme-name { + color: var(--tb-primary); +} + +/* UIkit 组件跟随主题色:UIkit 3.3.3 的主色是编译期常量(#1e87f0), + CSS 变量注入不进去,只能按组件覆盖。基础主题的 --tb-primary 恰好就是 #1e87f0, + 所以这段对默认外观零改动,只是让箱主主题能贯穿到按钮/链接/勾选。 */ +a, .uk-link { + color: var(--tb-primary); +} +a:hover, .uk-link:hover { + color: var(--tb-primary); +} +.uk-button-primary { + background-color: var(--tb-primary); +} +.uk-button-primary:hover, +.uk-button-primary:focus { + background-color: var(--tb-primary); + filter: brightness(1.07); +} +.uk-checkbox:checked, +.uk-checkbox:indeterminate, +.uk-radio:checked { + background-color: var(--tb-primary); + border-color: transparent; +} +.uk-input:focus, +.uk-select:focus, +.uk-textarea:focus { + border-color: var(--tb-primary); +} +.uk-tab > .uk-active > a { + border-color: var(--tb-primary); +} +.uk-text-primary { + color: var(--tb-primary) !important; +} + /* 轻量胶囊:用于投票类型、热门标签等「只是分类信息」的位置。 实心 uk-label 一屏多个会变成一排色块,这里统一降级为浅底 + 次要色文字。 */ .tb-chip { @@ -609,11 +711,13 @@ a.tb-chip:hover { border-radius: var(--tb-radius-xs); } .uk-progress::-webkit-progress-value { + /* 两端都圆:值 100% 时若只圆左边,右端方角会顶出轨道圆角 */ background-color: var(--tb-primary); - border-radius: var(--tb-radius-xs) 0 0 var(--tb-radius-xs); + border-radius: var(--tb-radius-xs); } .uk-progress::-moz-progress-bar { background-color: var(--tb-primary); + border-radius: var(--tb-radius-xs); } /* 移动端底部操作栏:固定底栏承载语言切换与深色模式,桌面端隐藏 */ diff --git a/outputs/preview-box-dark.html b/outputs/preview-box-dark.html index 540ff67..0232fda 100644 --- a/outputs/preview-box-dark.html +++ b/outputs/preview-box-dark.html @@ -3,7 +3,7 @@ - 预览 15:15 · + 预览 16:08 · @@ -636,7 +636,7 @@ document.getElementById("introcolor").style.color = "#ffffff"; href="/_/tester/1">查看回答
⭐ - 2026-10-19 15:15:39 + 2026-10-19 16:08:02

置顶的问题

@@ -648,7 +648,7 @@ document.getElementById("introcolor").style.color = "#ffffff"; href="/_/tester/2">查看回答
- 2026-10-19 14:15:39 + 2026-10-19 15:08:02

普通问题

diff --git a/outputs/preview-box-light.html b/outputs/preview-box-light.html index 53803f8..315813e 100644 --- a/outputs/preview-box-light.html +++ b/outputs/preview-box-light.html @@ -3,7 +3,7 @@ - 预览 15:15 · + 预览 16:08 · @@ -636,7 +636,7 @@ document.getElementById("introcolor").style.color = "#ffffff"; href="/_/tester/1">查看回答
⭐ - 2026-10-19 15:15:39 + 2026-10-19 16:08:02

置顶的问题

@@ -648,7 +648,7 @@ document.getElementById("introcolor").style.color = "#ffffff"; href="/_/tester/2">查看回答
- 2026-10-19 14:15:39 + 2026-10-19 15:08:02

普通问题

diff --git a/outputs/preview-explore-dark.html b/outputs/preview-explore-dark.html index 35634ce..ac452ff 100644 --- a/outputs/preview-explore-dark.html +++ b/outputs/preview-explore-dark.html @@ -3,7 +3,7 @@ - 预览 15:15 · 投票 + 预览 16:08 · 投票 diff --git a/outputs/preview-explore-light.html b/outputs/preview-explore-light.html index 1fd289a..79b40bc 100644 --- a/outputs/preview-explore-light.html +++ b/outputs/preview-explore-light.html @@ -3,7 +3,7 @@ - 预览 15:15 · 投票 + 预览 16:08 · 投票 diff --git a/outputs/preview-home-dark.html b/outputs/preview-home-dark.html index 869a8d3..3307990 100644 --- a/outputs/preview-home-dark.html +++ b/outputs/preview-home-dark.html @@ -3,7 +3,7 @@ - 预览 15:15 · TamaBox + 预览 16:08 · TamaBox diff --git a/outputs/preview-home-light.html b/outputs/preview-home-light.html index 77bf57d..55232ff 100644 --- a/outputs/preview-home-light.html +++ b/outputs/preview-home-light.html @@ -3,7 +3,7 @@ - 预览 15:15 · TamaBox + 预览 16:08 · TamaBox diff --git a/outputs/preview-profile-account-light.html b/outputs/preview-profile-account-light.html index 40e6b01..9efbf03 100644 --- a/outputs/preview-profile-account-light.html +++ b/outputs/preview-profile-account-light.html @@ -3,7 +3,7 @@ - 预览 15:15 · 设置 + 预览 16:08 · 设置 diff --git a/outputs/preview-profile-dark.html b/outputs/preview-profile-dark.html index c97656c..fcba1de 100644 --- a/outputs/preview-profile-dark.html +++ b/outputs/preview-profile-dark.html @@ -3,7 +3,7 @@ - 预览 15:15 · 设置 + 预览 16:08 · 设置 diff --git a/outputs/preview-profile-light.html b/outputs/preview-profile-light.html index 3fd0992..2e561dd 100644 --- a/outputs/preview-profile-light.html +++ b/outputs/preview-profile-light.html @@ -3,7 +3,7 @@ - 预览 15:15 · 设置 + 预览 16:08 · 设置 diff --git a/outputs/preview-profile-sakura-dark.html b/outputs/preview-profile-sakura-dark.html new file mode 100644 index 0000000..b633fb0 --- /dev/null +++ b/outputs/preview-profile-sakura-dark.html @@ -0,0 +1,2073 @@ + + + + + + 预览 16:08 · 设置 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+

裁剪图片

+
+
+
+ +
+

+
+ +
+
+ + +
+ + + + + +
+ + +
+
+ + + +
+

基础资料

+
+ + +
+
+ + +
+
+ +
+ +
+
+ + +
+
+ +
+ +
+
+ + + 选择访客访问你的提问箱时显示的语言(后台页面跟随此设置) +
+
+ + +
+
+ +
+
+ + +
+

头像与背景

+
+
+ + + + 1:1 +
+ + +
+ 裁剪框已锁定为 1:1 正方形 +
+
+ + + + 16:9 +
+ + +
+ 裁剪框已锁定为 16:9 宽屏 +
+
+ +
+ +
+
+ + +
+
    +
  • + 二维码样式 +
    +
    +
    +
    + +
    + +
    +
    + +
    + +
    +
    + +
    + +
    +
    + + 仅在启用时生效,否则颜色由系统自动生成 +
    +
    + +
    + + 0.35 + +
    +
    +
    + +
    + + 0.8 + +
    +
    +
    + +
    + + +
    + 选择图片后预览将即时更新 +
    +
    +
    +
    +

    实时预览

    +
    +
    +
    + 预设主题 +
    + + + + +
    +
    +
    + +
    +

    调整仅用于预览,最终效果点击「保存修改」后生效

    +
    +
    +
    +
    +
  • +
+
+ +
+
+ + +
+
    +
  • + 社交信息设置 +
    + 勾选后填写主页地址(无需 https://),未勾选的项将不会在前台显示。 + + + + + +
    +
  • +
+
+ +
+
+ + +
+

修改密码

+
+ + +
+
+ + +
+

保存后当前会话立即失效,需使用新密码重新登录

+
+
+ +
+
+
+ + +
+

标签设置

+
+ +
+ + +
+
+ +
+
+ +
+
+
+ + +
+

账号设置

+ +
+ + +
+

主题外观

+
+ +

仅对提问箱页面生效,站内其它页面保持默认外观。

+
+ + + + + + +
+
+ +
+
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + +

+
+ 社区规则 | + + 找站长 +
+ 盘 + | 公告板 + | 聊天室 + | 监控板 + | 导航页 +
Powered by NekoBox | +
提问箱已成功存活: +

+ + +
+
+ + + + + diff --git a/outputs/preview-profile-sakura-light.html b/outputs/preview-profile-sakura-light.html new file mode 100644 index 0000000..30d24e9 --- /dev/null +++ b/outputs/preview-profile-sakura-light.html @@ -0,0 +1,2073 @@ + + + + + + 预览 16:08 · 设置 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+

裁剪图片

+
+
+
+ +
+

+
+ +
+
+ + +
+ + + + + +
+ + +
+
+ + + +
+

基础资料

+
+ + +
+
+ + +
+
+ +
+ +
+
+ + +
+
+ +
+ +
+
+ + + 选择访客访问你的提问箱时显示的语言(后台页面跟随此设置) +
+
+ + +
+
+ +
+
+ + +
+

头像与背景

+
+
+ + + + 1:1 +
+ + +
+ 裁剪框已锁定为 1:1 正方形 +
+
+ + + + 16:9 +
+ + +
+ 裁剪框已锁定为 16:9 宽屏 +
+
+ +
+ +
+
+ + +
+
    +
  • + 二维码样式 +
    +
    +
    +
    + +
    + +
    +
    + +
    + +
    +
    + +
    + +
    +
    + + 仅在启用时生效,否则颜色由系统自动生成 +
    +
    + +
    + + 0.35 + +
    +
    +
    + +
    + + 0.8 + +
    +
    +
    + +
    + + +
    + 选择图片后预览将即时更新 +
    +
    +
    +
    +

    实时预览

    +
    +
    +
    + 预设主题 +
    + + + + +
    +
    +
    + +
    +

    调整仅用于预览,最终效果点击「保存修改」后生效

    +
    +
    +
    +
    +
  • +
+
+ +
+
+ + +
+
    +
  • + 社交信息设置 +
    + 勾选后填写主页地址(无需 https://),未勾选的项将不会在前台显示。 + + + + + +
    +
  • +
+
+ +
+
+ + +
+

修改密码

+
+ + +
+
+ + +
+

保存后当前会话立即失效,需使用新密码重新登录

+
+
+ +
+
+
+ + +
+

标签设置

+
+ +
+ + +
+
+ +
+
+ +
+
+
+ + +
+

账号设置

+ +
+ + +
+

主题外观

+
+ +

仅对提问箱页面生效,站内其它页面保持默认外观。

+
+ + + + + + +
+
+ +
+
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + +

+
+ 社区规则 | + + 找站长 +
+ 盘 + | 公告板 + | 聊天室 + | 监控板 + | 导航页 +
Powered by NekoBox | +
提问箱已成功存活: +

+ + +
+
+ + + + + diff --git a/outputs/preview-theme-sakura-dark.html b/outputs/preview-theme-sakura-dark.html index 1a0f586..ef7fdeb 100644 --- a/outputs/preview-theme-sakura-dark.html +++ b/outputs/preview-theme-sakura-dark.html @@ -3,7 +3,7 @@ - 预览 15:15 · + 预览 16:08 · @@ -22,13 +22,17 @@ - @@ -682,7 +687,7 @@ document.getElementById("introcolor").style.color = "#6b545c"; href="/_/tester/1">查看回答
⭐ - 2026-10-19 15:15:39 + 2026-10-19 16:08:02

置顶的问题

@@ -694,7 +699,7 @@ document.getElementById("introcolor").style.color = "#6b545c"; href="/_/tester/2">查看回答
- 2026-10-19 14:15:39 + 2026-10-19 15:08:02

普通问题

diff --git a/outputs/preview-theme-sakura-light.html b/outputs/preview-theme-sakura-light.html index 7f12ba3..6acd9ac 100644 --- a/outputs/preview-theme-sakura-light.html +++ b/outputs/preview-theme-sakura-light.html @@ -3,7 +3,7 @@ - 预览 15:15 · + 预览 16:08 · @@ -22,13 +22,17 @@ - @@ -682,7 +687,7 @@ document.getElementById("introcolor").style.color = "#6b545c"; href="/_/tester/1">查看回答
⭐ - 2026-10-19 15:15:39 + 2026-10-19 16:08:02

置顶的问题

@@ -694,7 +699,7 @@ document.getElementById("introcolor").style.color = "#6b545c"; href="/_/tester/2">查看回答
- 2026-10-19 14:15:39 + 2026-10-19 15:08:02

普通问题

diff --git a/outputs/sakura-before-after.png b/outputs/sakura-before-after.png new file mode 100644 index 0000000..cf6f1e5 Binary files /dev/null and b/outputs/sakura-before-after.png differ diff --git a/outputs/shot-new-default.png b/outputs/shot-new-default.png new file mode 100644 index 0000000..94a34a2 Binary files /dev/null and b/outputs/shot-new-default.png differ diff --git a/outputs/shot-new-sakura-dark.png b/outputs/shot-new-sakura-dark.png new file mode 100644 index 0000000..ea733e1 Binary files /dev/null and b/outputs/shot-new-sakura-dark.png differ diff --git a/outputs/shot-new-sakura-light.png b/outputs/shot-new-sakura-light.png new file mode 100644 index 0000000..1806dcd Binary files /dev/null and b/outputs/shot-new-sakura-light.png differ diff --git a/outputs/shot-preview-profile-sakura-dark.png b/outputs/shot-preview-profile-sakura-dark.png new file mode 100644 index 0000000..df956ed Binary files /dev/null and b/outputs/shot-preview-profile-sakura-dark.png differ diff --git a/outputs/shot-preview-profile-sakura-light.png b/outputs/shot-preview-profile-sakura-light.png new file mode 100644 index 0000000..a988470 Binary files /dev/null and b/outputs/shot-preview-profile-sakura-light.png differ diff --git a/outputs/shot-profile-full.png b/outputs/shot-profile-full.png new file mode 100644 index 0000000..c17b885 Binary files /dev/null and b/outputs/shot-profile-full.png differ diff --git a/outputs/shot-sakura-dark.png b/outputs/shot-sakura-dark.png new file mode 100644 index 0000000..f7a8318 Binary files /dev/null and b/outputs/shot-sakura-dark.png differ diff --git a/outputs/shot-sakura-light.png b/outputs/shot-sakura-light.png new file mode 100644 index 0000000..0573763 Binary files /dev/null and b/outputs/shot-sakura-light.png differ diff --git a/route/question/page.go b/route/question/page.go index 8a85273..874e480 100644 --- a/route/question/page.go +++ b/route/question/page.go @@ -78,7 +78,7 @@ func Pager(ctx context.Context) { } // 主题只作用于箱主相关页面(提问箱主页 / 单题页 / 密码页 / 分享卡路由), - // 与背景图、颜色同属箱主个性化配置;/user 后台保持中性外观。 + // 与背景图、颜色同属箱主个性化配置;/user 后台由 Contexter 按登录用户自己的配置注入。 // 空串 = 不加载主题 css(站点默认就是基础外观时省掉一次请求)。 ctx.Data["ThemeSlug"] = theme.Resolve(pageUser.Theme) // 页面密码检查 diff --git a/static/css/base.css b/static/css/base.css index 2e801ab..a18b14e 100644 --- a/static/css/base.css +++ b/static/css/base.css @@ -11,6 +11,8 @@ --tb-surface: #ffffff; --tb-surface-2: #f4f6f8; --tb-surface-hover: #f3f7ff; + /* 顶栏底色:默认跟随卡片面;主题想消除「纯白顶栏压在彩色底上」的割裂时单独覆盖 */ + --tb-navbar: var(--tb-surface); --tb-border: #e8eaee; --tb-text: #1f2329; --tb-text-secondary: #5c6370; @@ -138,7 +140,7 @@ color: var(--tb-text) !important; } html[data-theme="dark"] .uk-navbar-container { - background-color: var(--tb-surface) !important; + background-color: var(--tb-navbar, var(--tb-surface)) !important; color: var(--tb-text) !important; } html[data-theme="dark"] .uk-navbar-nav > li > a, @@ -323,7 +325,7 @@ box-shadow: var(--tb-shadow); } .uk-navbar-container:not(.uk-navbar-transparent) { - background-color: var(--tb-surface); + background-color: var(--tb-navbar, var(--tb-surface)); } /* 键盘可达性:仅在键盘聚焦时出现描边,鼠标点击不出现 */ .uk-button:focus-visible, diff --git a/static/css/themes/_scaffold.css b/static/css/themes/_scaffold.css index 25d1635..fb8800a 100644 --- a/static/css/themes/_scaffold.css +++ b/static/css/themes/_scaffold.css @@ -15,11 +15,13 @@ display / flex / grid、position 一律不动 —— 主题不是换皮模板。 3. 本文件不参与构建,仅作参考;真正生效的是同目录下的 .css。 - ── 可用的 19 个令牌 ────────────────────────────────────────────── + ── 可用的 20 个令牌 ────────────────────────────────────────────── 底色层 --tb-bg 页面底色(html/body) --tb-surface 卡片、输入框等前景面板 --tb-surface-2 次级面(标签底、进度条轨道、代码块) --tb-surface-hover 悬停底(列表行、下拉项) + --tb-navbar 顶栏底色(不写则同 --tb-surface; + 页面底色不是白时建议覆盖成 bg 或它的同色,否则顶栏会成为一条白带) 线条 --tb-border 边框、分隔线 文字 --tb-text 正文 --tb-text-secondary 次要文字(说明、meta) @@ -50,6 +52,7 @@ html[data-theme-style="SLUG"] { --tb-surface: #ffffff; --tb-surface-2: #f4f6f8; --tb-surface-hover: #f3f7ff; + --tb-navbar: var(--tb-surface); /* 顶栏底色,需要时改成 var(--tb-bg) */ --tb-border: #e8eaee; --tb-text: #1f2329; diff --git a/static/css/themes/sakura.css b/static/css/themes/sakura.css index 0350ba0..0a89c1c 100644 --- a/static/css/themes/sakura.css +++ b/static/css/themes/sakura.css @@ -1,10 +1,14 @@ -/* 樱花(sakura):粉调 + 细网点图案,纯 CSS 实现,不依赖图片素材。 - 复制 _scaffold.css 写的示例:只覆盖令牌,未改动任何布局。 */ +/* 樱花(sakura):粉调 + 极淡网点,纯 CSS 实现,不依赖图片素材。 + 只覆盖令牌,不改动任何布局。要点: + - 页面底色用纯色(不用渐变),保证整页色感一致; + - 顶栏与卡片都是「带粉调的暖白」而不是纯白,和粉底之间是过渡不是硬切; + - 网点放大到 24px、透明度降到 0.05,只作纸纹,不在留白处抢注意力。 */ html[data-theme-style="sakura"] { - --tb-bg: #fff6f8; - --tb-surface: #ffffff; - --tb-surface-2: #fdeef2; + --tb-bg: #fceef3; + --tb-surface: #fffafc; + --tb-surface-2: #fbe8ee; --tb-surface-hover: #fdf1f5; + --tb-navbar: #fff6f9; --tb-border: #f2dde4; --tb-text: #3a2b30; @@ -18,16 +22,17 @@ html[data-theme-style="sakura"] { --tb-shadow-hover: 0 1px 2px rgba(120, 60, 80, 0.07), 0 18px 40px -20px rgba(120, 60, 80, 0.30); --tb-page-image: none; - --tb-page-pattern: radial-gradient(circle at 1px 1px, rgba(229, 103, 143, 0.14) 1px, transparent 0); - --tb-page-pattern-size: 16px 16px; + --tb-page-pattern: radial-gradient(circle at 1px 1px, rgba(229, 103, 143, 0.05) 1px, transparent 1.4px); + --tb-page-pattern-size: 24px 24px; } html[data-theme="dark"][data-theme-style="sakura"] { --tb-bg: #241a1f; - --tb-surface: #2e2129; + --tb-surface: #2f2228; --tb-surface-2: #3a2a33; --tb-surface-hover: rgba(255, 138, 176, 0.10); - --tb-border: #49333d; + --tb-navbar: #2a1e24; + --tb-border: #4a333e; --tb-text: #f2e4e9; --tb-text-secondary: #c6aab4; @@ -40,6 +45,6 @@ html[data-theme="dark"][data-theme-style="sakura"] { --tb-shadow-hover: 0 1px 2px rgba(0, 0, 0, 0.40), 0 18px 40px -20px rgba(0, 0, 0, 0.68); --tb-page-image: none; - --tb-page-pattern: radial-gradient(circle at 1px 1px, rgba(255, 138, 176, 0.10) 1px, transparent 0); - --tb-page-pattern-size: 16px 16px; + --tb-page-pattern: radial-gradient(circle at 1px 1px, rgba(255, 138, 176, 0.05) 1px, transparent 1.4px); + --tb-page-pattern-size: 24px 24px; } diff --git a/static/tamabox.changelogs.json b/static/tamabox.changelogs.json index a843901..dedecb0 100644 --- a/static/tamabox.changelogs.json +++ b/static/tamabox.changelogs.json @@ -7,7 +7,7 @@ { "collectionId": "tamabox", "collectionName": "tamabox-changelogs", - "content": "新增:箱主主题功能。设置页可为主题箱主页与单题页选择配色,只影响配色、图案与整页背景,不影响布局;未选择时跟随站点默认主题。
\n新增:主题底稿 static/css/themes/_scaffold.css,复制改名为 <slug>.css 并在 [theme] available 登记即可新增一套主题,无需改模板;示例主题「樱花」。", + "content": "新增:箱主主题功能。设置页可为主题选择配色、图案与整页背景(不影响布局);提问箱页面(箱主页 / 单题页 / 密码页 / 分享卡)与箱主本人后台页面都会跟随所选主题,首页、探索等公开页保持站点默认外观;未选择时跟随站点默认主题。
\n新增:主题底稿 static/css/themes/_scaffold.css,复制改名为 <slug>.css 并在 [theme] available 登记即可新增一套主题,无需改模板;示例主题「樱花」。", "created": "2026-10-19 15:10:00.000Z", "id": "none", "published_at": "2026-10-19 15:10:00.000Z", diff --git a/templates/zz_preview_test.go b/templates/zz_preview_test.go index 6faa354..c0aaa29 100644 --- a/templates/zz_preview_test.go +++ b/templates/zz_preview_test.go @@ -80,19 +80,12 @@ func TestGenPreview(t *testing.T) { themeBox["PageUser"].(map[string]interface{})["Background"] = bgURI themeBox["PageUser"].(map[string]interface{})["Usernamecolor"] = "#3a2b30" themeBox["PageUser"].(map[string]interface{})["Introcolor"] = "#6b545c" - themeCSS, err := os.ReadFile(filepath.Join("..", "static", "css", "themes", "sakura.css")) - if err != nil { - t.Fatalf("read theme css: %v", err) - } for _, theme := range []string{"light", "dark"} { page, err := renderToString(t, "question/list", themeBox) if err != nil { t.Fatalf("render themed list: %v", err) } - // 预览页走 file://,把主题 css 内联进去(真实页面是一次带缓存的静态请求)。 - // 用正则匹配:预览数据里没有 StaticVersion,v 参数为空串,不能按固定串替换。 - link := regexp.MustCompile(``) - page = link.ReplaceAllString(page, "") + page = inlineThemeCSS(t, page, "sakura") writePreview(t, outDir, "preview-theme-sakura-"+theme+".html", page, theme, "../static") } @@ -159,6 +152,40 @@ func TestGenPreview(t *testing.T) { } writePreview(t, outDir, "preview-profile-account-"+theme+".html", page, theme, "../static") } + + // 设置页在箱主主题下的样子:/user 后台现在也会跟随本人主题, + // 需要确认「粉色页面 + 主题选择器」不会互相吃掉。 + profileSakura := profileBaseData() + profileSakura["Themes"] = profile["Themes"] + profileSakura["CurrentTheme"] = "sakura" + profileSakura["ActiveProfileTab"] = "account" + profileSakura["ThemeSlug"] = "sakura" + profileSakura["FeatureQuestion"] = nil + profileSakura["FeatureChat"] = nil + profileSakura["FeatureVote"] = nil + for _, theme := range []string{"light", "dark"} { + page, err := renderToString(t, "user/profile", profileSakura) + if err != nil { + t.Fatalf("render themed profile: %v", err) + } + page = inlineThemeCSS(t, page, "sakura") + writePreview(t, outDir, "preview-profile-sakura-"+theme+".html", page, theme, "../static") + } +} + +// inlineThemeCSS 把主题 换成内联 style:预览页走 file://,相对路径取不到。 +// 预览数据里没有 StaticVersion,v 参数为空串,所以按正则匹配而不是固定串替换。 +func inlineThemeCSS(t *testing.T, html, slug string) string { + t.Helper() + css, err := os.ReadFile(filepath.Join("..", "static", "css", "themes", slug+".css")) + if err != nil { + t.Fatalf("read theme css: %v", err) + } + link := regexp.MustCompile(``) + if !link.MatchString(html) { + t.Fatalf("主题 %s 的 未出现在页面里(ThemeSlug 没传到模板)", slug) + } + return link.ReplaceAllString(html, "") } // writePreview 把 CDN 换成可直连的镜像、钉死主题,仅用于本地预览。