chore(theme): 同步 YschTheme 再生产物 theme.ts(版本戳 20260923-1454-9619fbf)
build / build (push) Successful in 2m33s
build / build (push) Successful in 2m33s
仅版本戳注释行变化,正文与 20260921-1219-bb1637c 版一致;main 此前无该文件,本次新增。
This commit is contained in:
@@ -0,0 +1,79 @@
|
|||||||
|
/**
|
||||||
|
* 本文件由 YschTheme scripts/gen-theme.mjs 从 assets-src/pc/theme-core.js 生成(版本 20260923-1454-9619fbf),勿手改。
|
||||||
|
* 分发方式:YschTheme `npm run sync` 拷进各端 src/utils/theme.ts(与 ThemeSwitcher.vue 配套,MD5 对齐报告)。
|
||||||
|
* 运行时档位类名由 /static/js/yh-theme-init.js 在 <head> 内先行挂好,本模块只负责读写与切换。
|
||||||
|
*/
|
||||||
|
export type ThemeName = "blue" | "ocean" | "ink" | "violet" | "teal";
|
||||||
|
|
||||||
|
/** 定稿默认档:blue + side-deep + grad-on + 侧栏跟随(D1 拍板 deep) */
|
||||||
|
export interface ThemeState {
|
||||||
|
theme: ThemeName;
|
||||||
|
/** 侧栏深色(false=浅色档) */
|
||||||
|
sideDeep: boolean;
|
||||||
|
/** 顶栏渐变(联动侧栏竖向渐变) */
|
||||||
|
gradOn: boolean;
|
||||||
|
/** 侧栏颜色跟随顶栏品牌色(false=中性灰 side-plain) */
|
||||||
|
sideFollow: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface StorageLike {
|
||||||
|
getItem(k: string): string | null;
|
||||||
|
setItem(k: string, v: string): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const THEME_NAMES: readonly ThemeName[] = ["blue", "ocean", "ink", "violet", "teal"];
|
||||||
|
|
||||||
|
export const THEME_STORAGE_KEY = "yh-theme";
|
||||||
|
|
||||||
|
export const DEFAULT_THEME_STATE: ThemeState = {
|
||||||
|
theme: "blue",
|
||||||
|
sideDeep: true,
|
||||||
|
gradOn: true,
|
||||||
|
sideFollow: true
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 宽松解析:任一字段非法/缺失即回退默认档(脏数据不阻塞启动) */
|
||||||
|
export function parseThemeState(raw: string | null): ThemeState {
|
||||||
|
if (!raw) return { ...DEFAULT_THEME_STATE };
|
||||||
|
try {
|
||||||
|
const o = JSON.parse(raw);
|
||||||
|
if (!o || typeof o !== "object") return { ...DEFAULT_THEME_STATE };
|
||||||
|
return {
|
||||||
|
theme: THEME_NAMES.includes(o.theme) ? o.theme : DEFAULT_THEME_STATE.theme,
|
||||||
|
sideDeep: typeof o.sideDeep === "boolean" ? o.sideDeep : DEFAULT_THEME_STATE.sideDeep,
|
||||||
|
gradOn: typeof o.gradOn === "boolean" ? o.gradOn : DEFAULT_THEME_STATE.gradOn,
|
||||||
|
sideFollow: typeof o.sideFollow === "boolean" ? o.sideFollow : DEFAULT_THEME_STATE.sideFollow
|
||||||
|
};
|
||||||
|
} catch {
|
||||||
|
return { ...DEFAULT_THEME_STATE };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function loadThemeState(storage: StorageLike | undefined = globalThis.localStorage): ThemeState {
|
||||||
|
if (!storage) return { ...DEFAULT_THEME_STATE };
|
||||||
|
return parseThemeState(storage.getItem(THEME_STORAGE_KEY));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function saveThemeState(state: ThemeState, storage: StorageLike | undefined = globalThis.localStorage): void {
|
||||||
|
try {
|
||||||
|
storage?.setItem(THEME_STORAGE_KEY, JSON.stringify(state));
|
||||||
|
} catch {
|
||||||
|
/* 隐私模式/配额失败静默:仅丢持久化,不丢本次会话生效 */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 把状态落到根元素档位类名(幂等:先清后挂),返回传入的 state 便于链式 */
|
||||||
|
export function applyThemeState(state: ThemeState, root: HTMLElement = document.documentElement): ThemeState {
|
||||||
|
root.dataset.theme = state.theme;
|
||||||
|
root.classList.toggle("side-deep", state.sideDeep);
|
||||||
|
root.classList.toggle("side-light", !state.sideDeep);
|
||||||
|
root.classList.toggle("grad-on", state.gradOn);
|
||||||
|
root.classList.toggle("grad-off", !state.gradOn);
|
||||||
|
root.classList.toggle("side-plain", !state.sideFollow);
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 启动引导:各端 main.ts(或本仓 init 脚本的启动段)于挂载前调用,消除首帧闪色 */
|
||||||
|
export function initTheme(): ThemeState {
|
||||||
|
return applyThemeState(loadThemeState());
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user