extract color schema

This commit is contained in:
2026-07-14 11:52:56 +08:00
parent 36a8719d0f
commit 12ddaba231
6 changed files with 602 additions and 544 deletions
@@ -2632,7 +2632,7 @@
# 2026-05-20 陶泥儿主视觉配色回收为暖白/陶土橙
- 背景:用户要求只替换产品各界面的 UI 颜色,不改布局,并以两张陶泥儿主视觉图作为配色依据。
- 决策:平台亮色主题的主色回收到暖白 / 米杏底、陶土橙主按钮、深棕正文与浅杏边框;后台管理也同步切换到同一暖橙体系。主题变量优先通过 `src/index.css``--platform-*` token 统一控制,零散组件只做必要的局部替换。
- 决策:平台亮色主题的主色回收到暖白 / 米杏底、陶土橙主按钮、深棕正文与浅杏边框;后台管理也同步切换到同一暖橙体系。主题变量优先通过 `packages/shared/src/platform-theme.css``--platform-*` token 统一控制,零散组件只做必要的局部替换。
- 影响范围:主站平台壳层、常用表单 / 按钮 / 卡片 / 背景、后台管理 UI、业务进度条和小游戏结果条的通用强调色。
- 验证方式:优先检查 `src/index.css``apps/admin-web/src/styles/admin.css` 是否还存在旧粉色主色;再用编码检查和可执行的本地 typecheck / build 验证。
- 关联文档:`docs/【项目基线】当前产品与工程约束-2026-05-15.md`
@@ -108,7 +108,7 @@ server-rs + Axum + SpacetimeDB
12. “我的”页泥点余额、累计游玩、已玩游戏三张统计卡只展示各自标签和值,三个统计 icon 使用小尺寸普通 UI 档位,内容不换行,不在统计区底部展示“更新于”时间;移动端昵称、常用功能和法律信息也应保持 `10px``14px` 的普通 UI 字号区间,避免展示级字号挤压内容。
13. 移动端“我的”页需要兼容窄屏:头像 / 昵称 / 陶泥号、三张统计卡、五项常用功能和法律信息都必须能在底部固定 TabBar 上方完整滚动露出,不得与底部 dock、刘海 safe-area 或相邻 UI 元素遮挡重叠。
14. RPG 等运行态的战斗飘字、血量变化和即时反馈必须在暗色、噪声高的场景背景上保持可读:使用高亮文字、深色描边、强阴影或小面积半透明底,不只依赖红/绿文字本身表达伤害或治疗。
15. 平台亮色 UI 配色以陶泥儿主视觉为准:暖白 / 米杏底、陶土橙主按钮、深棕正文与浅杏边框;新增界面优先复用 `src/index.css``--platform-*` 主题变量和 `apps/admin-web/src/styles/admin.css` 的同系色值,不再引入粉红、蓝绿等独立主色方案。
15. 平台亮色 UI 配色以陶泥儿主视觉为准:暖白 / 米杏底、陶土橙主按钮、深棕正文与浅杏边框;新增界面优先复用 `packages/shared/src/platform-theme.css``--platform-*` 主题变量和 `apps/admin-web/src/styles/admin.css` 的同系色值,不再引入粉红、蓝绿等独立主色方案。
## 文案与编码
File diff suppressed because it is too large Load Diff
+45
View File
@@ -0,0 +1,45 @@
import fs from 'node:fs';
import path from 'node:path';
import {describe, expect, it} from 'vitest';
const themePath = path.resolve(
process.cwd(),
'packages/shared/src/platform-theme.css',
);
function getCssBlock(source: string, selector: string) {
const selectorIndex = source.indexOf(selector);
expect(selectorIndex, `${selector} should exist`).toBeGreaterThanOrEqual(0);
const openBraceIndex = source.indexOf('{', selectorIndex);
let depth = 0;
for (let index = openBraceIndex; index < source.length; index += 1) {
const char = source[index];
if (char === '{') {
depth += 1;
} else if (char === '}') {
depth -= 1;
if (depth === 0) {
return source.slice(openBraceIndex + 1, index);
}
}
}
throw new Error(`${selector} block is not closed`);
}
describe('shared platform theme', () => {
it('keeps the light and dark semantic color contracts', () => {
const css = fs.readFileSync(themePath, 'utf8');
const light = getCssBlock(css, '.platform-theme--light');
const dark = getCssBlock(css, '.platform-theme--dark');
expect(light).toContain('--platform-accent: #c7653d;');
expect(light).toContain('linear-gradient(135deg, #df7f40, #b95d3a)');
expect(light).toContain('--platform-text-strong: #3d1f10;');
expect(dark).toContain('--platform-accent: #5b6cff;');
expect(dark).toContain('linear-gradient(135deg, #5b6cff, #3dd9ff)');
expect(dark).toContain('--platform-text-strong: #ffffff;');
});
});
+1 -538
View File
File diff suppressed because it is too large Load Diff
+16 -4
View File
@@ -7,6 +7,13 @@ function readIndexCss() {
return fs.readFileSync(path.resolve(process.cwd(), 'src/index.css'), 'utf8');
}
function readPlatformThemeCss() {
return fs.readFileSync(
path.resolve(process.cwd(), 'packages/shared/src/platform-theme.css'),
'utf8',
);
}
function getCssBlock(source: string, selector: string) {
const selectorIndex = source.indexOf(selector);
expect(selectorIndex, `${selector} should exist in src/index.css`).toBeGreaterThanOrEqual(0);
@@ -194,11 +201,16 @@ describe('index stylesheet unread dots', () => {
it('uses warm brown tokens for draft unread markers instead of red literals', () => {
const css = readIndexCss();
const themeCss = readPlatformThemeCss();
expect(css).toContain('--platform-unread-dot-fill: #8b5a3d;');
expect(css).toContain('--platform-unread-dot-glow: rgba(139, 90, 61, 0.34);');
expect(css).toContain('--platform-unread-dot-fill: #d6a27c;');
expect(css).toContain('--platform-unread-dot-glow: rgba(214, 162, 124, 0.24);');
expect(themeCss).toContain('--platform-unread-dot-fill: #8b5a3d;');
expect(themeCss).toContain(
'--platform-unread-dot-glow: rgba(139, 90, 61, 0.34);',
);
expect(themeCss).toContain('--platform-unread-dot-fill: #d6a27c;');
expect(themeCss).toContain(
'--platform-unread-dot-glow: rgba(214, 162, 124, 0.24);',
);
for (const selector of [
'.creation-work-card__unread-dot',