mirror of
https://github.com/zyycn/codex-proxy-rs.git
synced 2026-11-11 16:06:13 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dad91fe9f7 | ||
|
|
b22b0cfa41 |
+7
-11
@@ -27,8 +27,7 @@
|
||||
- **Seed 与 Map 可追踪**:主色和功能色均按 Ant Design 从 Seed 派生 P1-P10;浅色 P6 等于 Seed,深色 P6
|
||||
经过暗色色板适配。全局 `colorPrimary` 保留原始 Seed;功能色 Base 保留 P6。文字和按钮组件可在派生层做对比度校正,Seed 不随之改写
|
||||
- **主色与表面分离**:品牌色负责交互和强调,页面、容器、浮层与文字由独立的背景和文本 Seed 派生
|
||||
- **语义独立**:`success`、`warning`、`error`、`info` 不随品牌色隐式改变;未显式配置 `link`
|
||||
时跟随 `primary`,显式配置后独立派生
|
||||
- **语义独立**:成功、警告、错误、信息和链接色各自派生,不随品牌色改变
|
||||
- **无边设计**:默认依靠表面色差、间距和轻阴影表达层级;边框只用于焦点、错误和必要分隔
|
||||
- **运行时可定制**:用户输入在浏览器中实时派生,因此使用 CSS Variables,不使用构建时 SCSS 变量
|
||||
- **单一事实源**:Store 只保存最小配置,所有 Map、Alias 与未覆盖的 Component Token 均由纯函数生成
|
||||
@@ -158,7 +157,7 @@ interface ThemeCustomization {
|
||||
|
||||
表格行高与卡片圆角通过 `customization.component` 的 `tableRowHeight`、`cardBorderRadius` 配置,属于组件尺寸覆盖
|
||||
|
||||
完整主题预设组合品牌配色、推荐材质、全局 Seed、组件尺寸和可编辑 Token。选择时替换草稿配置,保留当前明暗模式;保存后应用到管理端
|
||||
切换内置主题预设会更新草稿中的品牌色、材质、尺寸与风格,保留明暗模式以及「功能色与中性色」的设置;保存后应用到管理端
|
||||
|
||||
表面材质可单独选择:`default` 使用简洁表面,`soft` 使用柔和光影。材质只影响表面高光、渐变与阴影,不改变配色、圆角、字号或组件尺寸
|
||||
|
||||
@@ -206,10 +205,8 @@ Preset 的实心色使用 P6,普通 Container、Strong Container 与边界按
|
||||
- `colorText / Heading / Secondary / Tertiary / Quaternary / Disabled`
|
||||
- `colorBorder / BorderSecondary / Split / Shadow`
|
||||
|
||||
星津夜航使用稳定的浅色 / 深色中性基线;水墨江汀、粉墙回廊与朱阙金瓦预置额外提供各自的 `colorBgBase`、`colorTextBase`
|
||||
画像,自定义主色则只向通用中性基线注入少量色温。默认浅色采用中性锚点,默认深色使用 HSL 色调派生;带色温
|
||||
主题按外观距离平滑过渡到背景和文字 Seed 的 RGB 混色结果。稳定锚点用于 Surface 与 Shadow,Component 从角色派生,
|
||||
所有预置、自定义 Seed 和用户覆盖仍进入同一条算法,不在页面或组件中追加 HEX 特判。
|
||||
所有品牌色共用当前明暗模式的背景和文字基色。手动设置 `colorBgBase` 或 `colorTextBase` 后,两个模式都使用该字段的自定义值;单项恢复后重新跟随明暗模式。
|
||||
默认浅色采用中性锚点,默认深色使用 HSL 色调派生;自定义中性色按外观距离平滑过渡到背景和文字 Seed 的 RGB 混色结果。
|
||||
Input、阴影与其他 Component Token 从 Fill、Surface、Primary 和 Semantic 派生,不在常量文件维护整套颜色表
|
||||
|
||||
正常文字同时检查 Layout、Container、Elevated、文字交互背景、三级 Fill,以及控件透明填充在各宿主上的合成色
|
||||
@@ -291,7 +288,7 @@ Purple Strong Container 或 Purple Solid;同一组颜色仍由运行时色板
|
||||
| ID | 名称 | 推荐品牌色 | 表面 |
|
||||
| --- | --- | --- | --- |
|
||||
| `default` | 默认 | 星津夜航 | 简洁表面与轻量阴影 |
|
||||
| `soft` | 柔光 | 星津夜航 | 表面高光与分层阴影,配色跟随品牌 |
|
||||
| `soft` | 柔光 | 星津夜航 | 表面高光、渐变与分层阴影 |
|
||||
|
||||
### 主题预设
|
||||
|
||||
@@ -302,8 +299,7 @@ Purple Strong Container 或 Purple Solid;同一组颜色仍由运行时色板
|
||||
| `signal-violet` | 粉墙回廊 | `#D395A8` | 默认材质,14px 正文与 68px 表格行高 |
|
||||
| `graphite` | 朱阙金瓦 | `#A34537` | 柔光,12px 卡片圆角与 54px 表格行高 |
|
||||
|
||||
品牌配色改变品牌主色,并可提供与该品牌匹配的浅色 / 深色背景和文字 Seed;不改变字号、密度、圆角或布局。完整预设提供的 Seed 优先于品牌基线,用户覆盖优先于预设
|
||||
所有预置与自定义主题走同一条 Surface、Map、Alias 与 Component 派生链路,不存在页面级特判
|
||||
单独编辑品牌主色不改变尺寸和风格。预置与自定义主题使用相同的 Surface、Map、Alias 与 Component 派生链路
|
||||
|
||||
## 运行时架构
|
||||
|
||||
@@ -448,7 +444,7 @@ utility / arbitrary variant;Vue Transition、跨浏览器 Range、动态富文
|
||||
|
||||
### 增加预置主题
|
||||
|
||||
在 UI 库的 `themeProfiles` 中组合配色 ID 对应的材质与 `ThemeCustomization`。设置页将其复制为可编辑草稿,保存实际配置,无需持久化额外的选中标记。材质仍由组件 Token 派生层实现
|
||||
在 UI 库的 `themeProfiles` 中为每个配色 ID 配置材质与 `ThemeCustomization`。内置预设不指定功能色与中性色。设置页通过 `resolveThemeProfile` 应用预设,保留预设未指定的颜色;选中状态由同一结果推导。材质由组件 Token 派生层实现
|
||||
|
||||
单独增加品牌配色:
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@boxicons/vue": "1.0.1",
|
||||
"@codex-proxy/ui": "github:zyycn/codex-proxy-ui#v0.9.1",
|
||||
"@codex-proxy/ui": "github:zyycn/codex-proxy-ui#v0.10.0",
|
||||
"@fontsource-variable/inter": "^5.3.0",
|
||||
"@fontsource-variable/jetbrains-mono": "^5.3.0",
|
||||
"@lucide/vue": "^1.70.0",
|
||||
|
||||
Generated
+6
-6
@@ -195,8 +195,8 @@ importers:
|
||||
specifier: 1.0.1
|
||||
version: 1.0.1(vue@3.5.45(typescript@6.0.3))
|
||||
'@codex-proxy/ui':
|
||||
specifier: github:zyycn/codex-proxy-ui#v0.9.1
|
||||
version: https://codeload.github.com/zyycn/codex-proxy-ui/tar.gz/46ade64479009ab9bc7cb1c8ec6d143fbd0a3b6c(axios@1.21.0(debug@4.4.3))(change-case@5.4.4)(jiti@2.7.0)(postcss@8.5.30)(vite@8.3.6(@types/node@26.6.6)(jiti@2.7.0)(yaml@2.9.0))(vue@3.5.45(typescript@6.0.3))(yaml@2.9.0)
|
||||
specifier: github:zyycn/codex-proxy-ui#v0.10.0
|
||||
version: https://codeload.github.com/zyycn/codex-proxy-ui/tar.gz/45b076735d67f973588d93144078c7605cf1ade7(axios@1.21.0(debug@4.4.3))(change-case@5.4.4)(jiti@2.7.0)(postcss@8.5.30)(vite@8.3.6(@types/node@26.6.6)(jiti@2.7.0)(yaml@2.9.0))(vue@3.5.45(typescript@6.0.3))(yaml@2.9.0)
|
||||
'@fontsource-variable/inter':
|
||||
specifier: ^5.3.0
|
||||
version: 5.3.0
|
||||
@@ -456,9 +456,9 @@ packages:
|
||||
resolution: {integrity: sha512-dlT1m5e/0yUL0kRNcQn7yGLVThkgbB0Ga/1AmfDDC/8ik6AIiSf2QLQO2zPYvefsHP0aFgxO93cVLCCfDp7kzQ==}
|
||||
engines: {node: '>= 20.12.0'}
|
||||
|
||||
'@codex-proxy/ui@https://codeload.github.com/zyycn/codex-proxy-ui/tar.gz/46ade64479009ab9bc7cb1c8ec6d143fbd0a3b6c':
|
||||
resolution: {gitHosted: true, integrity: sha512-4gsO8MKvqlYmi1+TbgVt0r2EabvYzPJ2YpvhrLlyQz0EPX+jhA6mK0ZXOlDRSSs7/AIZ8Ihfi+zvVFfSIVLdxg==, tarball: https://codeload.github.com/zyycn/codex-proxy-ui/tar.gz/46ade64479009ab9bc7cb1c8ec6d143fbd0a3b6c}
|
||||
version: 0.9.1
|
||||
'@codex-proxy/ui@https://codeload.github.com/zyycn/codex-proxy-ui/tar.gz/45b076735d67f973588d93144078c7605cf1ade7':
|
||||
resolution: {gitHosted: true, integrity: sha512-TyY1/D8rzd1MwU5HUbKOEzca5q7nPqydWaRpb5iMUrSy6G4dXleZNSZd6VXAum9WXZrZGb9ZzBm9cOMIOg+/xg==, tarball: https://codeload.github.com/zyycn/codex-proxy-ui/tar.gz/45b076735d67f973588d93144078c7605cf1ade7}
|
||||
version: 0.10.0
|
||||
engines: {node: '>=24'}
|
||||
peerDependencies:
|
||||
vite: ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0
|
||||
@@ -3530,7 +3530,7 @@ snapshots:
|
||||
fast-wrap-ansi: 0.2.2
|
||||
sisteransi: 1.0.5
|
||||
|
||||
'@codex-proxy/ui@https://codeload.github.com/zyycn/codex-proxy-ui/tar.gz/46ade64479009ab9bc7cb1c8ec6d143fbd0a3b6c(axios@1.21.0(debug@4.4.3))(change-case@5.4.4)(jiti@2.7.0)(postcss@8.5.30)(vite@8.3.6(@types/node@26.6.6)(jiti@2.7.0)(yaml@2.9.0))(vue@3.5.45(typescript@6.0.3))(yaml@2.9.0)':
|
||||
'@codex-proxy/ui@https://codeload.github.com/zyycn/codex-proxy-ui/tar.gz/45b076735d67f973588d93144078c7605cf1ade7(axios@1.21.0(debug@4.4.3))(change-case@5.4.4)(jiti@2.7.0)(postcss@8.5.30)(vite@8.3.6(@types/node@26.6.6)(jiti@2.7.0)(yaml@2.9.0))(vue@3.5.45(typescript@6.0.3))(yaml@2.9.0)':
|
||||
dependencies:
|
||||
'@ant-design/colors': 8.0.1
|
||||
'@ant-design/fast-color': 3.0.1
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<script setup lang="ts">
|
||||
import type { Theme, ThemeColorPresetId, ThemeMode, ThemePresetId, ThemeSeedOverrides } from '@codex-proxy/ui/theme'
|
||||
import type { Theme, ThemeColorPresetId, ThemeMode, ThemePresetId, ThemeSeedColors, ThemeSeedDimensions, ThemeSeedOverrides } from '@codex-proxy/ui/theme'
|
||||
|
||||
import type { ThemeEditorDraft, ThemeEditorGlobalCategory } from '../composables/useThemeEditor'
|
||||
import { ZSegmented } from '@codex-proxy/ui'
|
||||
|
||||
import { createThemeSeedTokens, themeColorPresets, themePresets, themeProfiles } from '@codex-proxy/ui/theme'
|
||||
import { resolveThemeProfile, themeColorPresets, themePresets } from '@codex-proxy/ui/theme'
|
||||
import { Check, ChevronDown, Laptop, Moon, PanelsTopLeft, Sparkles, Sun } from '@lucide/vue'
|
||||
|
||||
import { isEqual } from 'es-toolkit'
|
||||
@@ -28,17 +28,8 @@ const emit = defineEmits<{
|
||||
resetPrimary: []
|
||||
profile: [value: ThemeColorPresetId]
|
||||
primary: [value: string]
|
||||
seedColor: [
|
||||
key: Exclude<
|
||||
keyof ThemeSeedOverrides,
|
||||
'fontSize' | 'sizeUnit' | 'sizeStep' | 'controlHeight' | 'borderRadius' | 'shadowStrength'
|
||||
>,
|
||||
value: string,
|
||||
]
|
||||
seedNumber: [
|
||||
key: 'fontSize' | 'sizeUnit' | 'sizeStep' | 'controlHeight' | 'borderRadius' | 'shadowStrength',
|
||||
value: number,
|
||||
]
|
||||
seedColor: [key: keyof ThemeSeedColors, value: string]
|
||||
seedNumber: [key: keyof ThemeSeedDimensions, value: number]
|
||||
resetSeed: [key: keyof ThemeSeedOverrides]
|
||||
}>()
|
||||
|
||||
@@ -47,25 +38,18 @@ const { t } = useI18n({ useScope: 'global' })
|
||||
const category = defineModel<ThemeEditorGlobalCategory>('category', { required: true })
|
||||
const derivedOpen = shallowRef(false)
|
||||
|
||||
const profiles = themeColorPresets.map((preset) => {
|
||||
const options = { ...themeProfiles[preset.id], colorId: preset.id }
|
||||
const light = createThemeSeedTokens({ ...options, scheme: 'light' })
|
||||
return {
|
||||
...preset,
|
||||
paper: light.colorBgBase,
|
||||
accent: light.colorWarning,
|
||||
ink: createThemeSeedTokens({ ...options, scheme: 'dark' }).colorBgBase,
|
||||
}
|
||||
})
|
||||
const localizedPresets = computed(() => profiles.map(p => ({
|
||||
const localizedPresets = computed(() => themeColorPresets.map(p => ({
|
||||
...p,
|
||||
...uiLocale.value.theme[p.id],
|
||||
})))
|
||||
const activeProfile = computed(() => {
|
||||
const { color, preset, customization } = props.draft
|
||||
if (color !== 'custom' && themeProfiles[color].preset === preset && isEqual(themeProfiles[color].customization, customization))
|
||||
return color
|
||||
return undefined
|
||||
if (color === 'custom')
|
||||
return undefined
|
||||
const profile = resolveThemeProfile(color, customization.seed)
|
||||
return profile.preset === preset && isEqual(profile.customization, customization)
|
||||
? color
|
||||
: undefined
|
||||
})
|
||||
const colorPresets = themeColorPresets.map(preset => preset.seed)
|
||||
const themePresetDetails = computed(() => ({
|
||||
@@ -215,7 +199,7 @@ function seedOverridden(key: keyof ThemeSeedOverrides) {
|
||||
>
|
||||
<svg
|
||||
class="block h-11 w-full overflow-hidden rounded-z-sm"
|
||||
:style="{ 'color': preset.seed, '--scene-paper': preset.paper, '--scene-ink': preset.ink, '--scene-accent': preset.accent }"
|
||||
:style="{ color: preset.seed }"
|
||||
viewBox="0 0 160 44"
|
||||
preserveAspectRatio="xMidYMid slice"
|
||||
aria-hidden="true"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg">
|
||||
<symbol id="relay-blue" viewBox="0 0 160 44" preserveAspectRatio="xMidYMid slice">
|
||||
<symbol id="relay-blue" viewBox="0 0 160 44" preserveAspectRatio="xMidYMid slice" style="--scene-paper: #FFFFFF; --scene-ink: #111A29">
|
||||
<path fill="var(--scene-ink)" d="M0 0h160v44H0z"/>
|
||||
<path fill="currentColor" opacity=".3" d="M0 34q25-4 56-1t58-1q25-2 46 0v12H0z"/>
|
||||
<path fill="none" stroke="currentColor" opacity=".7" d="m14 16 12-8 13 6 15-7"/>
|
||||
@@ -12,7 +12,7 @@
|
||||
<path fill="currentColor" d="m109 20 5 9h-5zm-13 11h21l-4 3h-12z"/>
|
||||
<path fill="none" stroke="currentColor" opacity=".65" stroke-linecap="round" d="m85 36 14-.5m5 3 6-.5"/>
|
||||
</symbol>
|
||||
<symbol id="deep-teal" viewBox="0 0 160 44" preserveAspectRatio="xMidYMid slice">
|
||||
<symbol id="deep-teal" viewBox="0 0 160 44" preserveAspectRatio="xMidYMid slice" style="--scene-paper: #F8F8F3; --scene-ink: #202727">
|
||||
<path fill="var(--scene-paper)" d="M0 0h160v44H0z"/>
|
||||
<g fill="currentColor">
|
||||
<path opacity=".18" d="m0 18 12-5 9 1 15-9 7 2 6-3 14 12 8-3 13 6 16-9 8 2 12-6 17 12 9-3 14 4v5H0z"/>
|
||||
@@ -27,21 +27,21 @@
|
||||
<path fill="var(--scene-ink)" d="M100 30q5 2 16 0l-3 2h-9z"/>
|
||||
<path fill="none" stroke="var(--scene-ink)" stroke-linecap="round" d="m110 30-1-2-2 2m2-1 6 4"/>
|
||||
</symbol>
|
||||
<symbol id="signal-violet" viewBox="0 0 160 44" preserveAspectRatio="xMidYMid slice">
|
||||
<symbol id="signal-violet" viewBox="0 0 160 44" preserveAspectRatio="xMidYMid slice" style="--scene-paper: #FCF6F7; --scene-ink: #29242A">
|
||||
<path fill="var(--scene-paper)" d="M0 0h160v44H0z"/>
|
||||
<path fill="currentColor" d="M0 5l57 10v29H0zM74 18l26 5v21H74zM119 24l13 2v18h-13z"/>
|
||||
<path fill="var(--scene-ink)" opacity=".57" d="M57 15l10-4v33H57zM100 23l5-2v23h-5zM132 26l4-1v19h-4z"/>
|
||||
<path fill="currentColor" opacity=".28" d="M0 44l160-13v13z"/>
|
||||
<circle cx="143" cy="10" r="4" fill="currentColor"/>
|
||||
</symbol>
|
||||
<symbol id="graphite" viewBox="0 0 160 44" preserveAspectRatio="xMidYMid slice">
|
||||
<symbol id="graphite" viewBox="0 0 160 44" preserveAspectRatio="xMidYMid slice" fill="#BD8C3F" style="--scene-paper: #FBF5E8; --scene-ink: #302421">
|
||||
<path fill="var(--scene-paper)" d="M0 0h160v44H0z"/>
|
||||
<path fill="currentColor" d="M0 33h160v11H0zM26 21h5v16h-5zm21 0h5v16h-5zm22 0h5v16h-5zm23 0h5v16h-5zm22 0h5v16h-5zm20 0h5v16h-5z"/>
|
||||
<path fill="var(--scene-ink)" d="M22 18h120l-5 5H28z"/>
|
||||
<path fill="var(--scene-accent)" d="M12 14q12 6 28-1 8-3 15-11h55q7 8 15 11 14 6 27 1-4 7-19 7H32q-15 0-20-7z"/>
|
||||
<path d="M12 14q12 6 28-1 8-3 15-11h55q7 8 15 11 14 6 27 1-4 7-19 7H32q-15 0-20-7z"/>
|
||||
<path fill="none" stroke="var(--scene-ink)" stroke-width="1.4" d="M12 15q8 7 24 6h94q15 1 22-6M54 2h57"/>
|
||||
<path fill="none" stroke="var(--scene-paper)" opacity=".5" d="m56 5-10 10m20-10-5 10m15-10-2 10m13-10 1 10m10-10 4 10m6-10 8 10"/>
|
||||
<path fill="var(--scene-accent)" d="M0 33h160v2H0z"/>
|
||||
<path d="M0 33h160v2H0z"/>
|
||||
<path fill="var(--scene-ink)" opacity=".25" d="M0 40h160v4H0z"/>
|
||||
</symbol>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.2 KiB |
@@ -6,6 +6,8 @@ import type {
|
||||
ThemeMode,
|
||||
ThemePresetId,
|
||||
ThemeScheme,
|
||||
ThemeSeedColors,
|
||||
ThemeSeedDimensions,
|
||||
ThemeSeedOverrides,
|
||||
ThemeTokenName,
|
||||
} from '@codex-proxy/ui/theme'
|
||||
@@ -22,7 +24,7 @@ import {
|
||||
isThemeMode,
|
||||
isThemePresetId,
|
||||
normalizeThemeCustomization,
|
||||
themeProfiles,
|
||||
resolveThemeProfile,
|
||||
} from '@codex-proxy/ui/theme'
|
||||
|
||||
import { storeToRefs } from 'pinia'
|
||||
@@ -48,9 +50,7 @@ export interface ThemeEditorDraft {
|
||||
customization: ThemeCustomization
|
||||
}
|
||||
|
||||
type NumericSeedKey = 'fontSize' | 'sizeUnit' | 'sizeStep' | 'controlHeight' | 'borderRadius' | 'shadowStrength'
|
||||
type ComponentNumberKey = keyof ThemeComponentOverrides
|
||||
type ColorSeedKey = Exclude<keyof ThemeSeedOverrides, NumericSeedKey>
|
||||
|
||||
export function useThemeEditor() {
|
||||
const themeStore = useThemeStore()
|
||||
@@ -125,13 +125,11 @@ export function useThemeEditor() {
|
||||
}
|
||||
|
||||
function applyProfile(color: ThemeColorPresetId) {
|
||||
const { preset, customization } = themeProfiles[color]
|
||||
draft.value = {
|
||||
...draft.value,
|
||||
color,
|
||||
preset,
|
||||
customColor: defaultThemePrimaryColor,
|
||||
customization: normalizeThemeCustomization(customization),
|
||||
...resolveThemeProfile(color, draft.value.customization.seed),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,14 +155,14 @@ export function useThemeEditor() {
|
||||
: mode
|
||||
}
|
||||
|
||||
function setSeedColor(key: ColorSeedKey, color: string) {
|
||||
function setSeedColor(key: keyof ThemeSeedColors, color: string) {
|
||||
const normalized = normalizeHexColor(color)
|
||||
if (!normalized)
|
||||
return
|
||||
updateSeed({ [key]: normalized })
|
||||
}
|
||||
|
||||
function setSeedNumber(key: NumericSeedKey, value: number) {
|
||||
function setSeedNumber(key: keyof ThemeSeedDimensions, value: number) {
|
||||
if (!Number.isFinite(value))
|
||||
return
|
||||
updateSeed({ [key]: value })
|
||||
|
||||
+1
-1
Submodule modules/ui updated: 46ade64479...45b076735d
@@ -1,7 +1,7 @@
|
||||
version: 3.45.2
|
||||
published:
|
||||
'3':
|
||||
stable: 3.45.1
|
||||
rc: 3.45.1
|
||||
beta: 3.45.1
|
||||
alpha: 3.45.1
|
||||
stable: 3.45.2
|
||||
rc: 3.45.2
|
||||
beta: 3.45.2
|
||||
alpha: 3.45.2
|
||||
|
||||
Reference in New Issue
Block a user