mirror of
https://gitee.com/spark-store-project/spark-store
synced 2026-09-20 13:40:11 +08:00
feat(settings): 新增字体大小设置(仅字号档位,不含整体缩放/字体族)
- 新增 src/global/displaySettings.ts:small/medium/large/xlarge 四档 → html 15/16/17/18px, localStorage(spark-store-font-size) 持久化,applyFontSize 写 html font-size 全局联动 rem 字号类 - App.vue onMounted 最前 initFontSize()(与 initTagPriorityStrategy 同级,防字号闪烁) - SettingsModal.vue 新增「字体大小」卡片(4 档分段按钮 + 预览),selectFontSize 即时应用+持久化 - 用户确认范围:仅字号档位,整体缩放与字体族切换本期不做 - vue-tsc/lint/打包均通过
This commit is contained in:
Vendored
+1
-1
@@ -1,4 +1,4 @@
|
||||
spark-store (5.3.0.1) UNRELEASED; urgency=medium
|
||||
spark-store (5.3.0.2-test) UNRELEASED; urgency=medium
|
||||
|
||||
* Initial release.
|
||||
|
||||
|
||||
@@ -344,6 +344,7 @@ import ReviewUserProfileModal from "./components/ReviewUserProfileModal.vue";
|
||||
import WindowTitleBar from "./components/WindowTitleBar.vue";
|
||||
import SubmitterWindow from "./components/SubmitterWindow.vue";
|
||||
import { initTagPriorityStrategy } from "./global/tagPriority";
|
||||
import { initFontSize } from "./global/displaySettings";
|
||||
import {
|
||||
FLARUM_BASE_URL,
|
||||
FLARUM_REGISTER_URL,
|
||||
@@ -1052,6 +1053,8 @@ onMounted(async () => {
|
||||
// 应用启动即锁定标签优先显示策略的真实持久化值,避免依赖详情页挂载顺序
|
||||
// 导致先读到内存默认值 "auto" 再懒加载的竞态窗口。
|
||||
initTagPriorityStrategy();
|
||||
// 恢复并应用持久化的字体大小档位(仅字号),避免渲染瞬间默认字号闪烁。
|
||||
initFontSize();
|
||||
initTheme();
|
||||
updateCenterStore.bind();
|
||||
|
||||
|
||||
@@ -163,6 +163,56 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 字体大小(字号档位:小 / 标准 / 大 / 特大) -->
|
||||
<div
|
||||
class="rounded-2xl border border-slate-200/60 bg-slate-50/50 px-4 py-4 dark:border-slate-800/60 dark:bg-slate-800/50"
|
||||
>
|
||||
<div class="flex items-start gap-3">
|
||||
<div
|
||||
class="flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-xl bg-pink-100 text-pink-600 dark:bg-pink-900/30 dark:text-pink-400"
|
||||
>
|
||||
<i class="fas fa-font"></i>
|
||||
</div>
|
||||
<div class="min-w-0 flex-1">
|
||||
<p
|
||||
class="text-sm font-medium text-slate-800 dark:text-slate-200"
|
||||
>
|
||||
字体大小
|
||||
</p>
|
||||
<p class="text-xs text-slate-500 dark:text-slate-400">
|
||||
调整全局界面字体大小(仅字号)
|
||||
</p>
|
||||
<div
|
||||
class="mt-3 inline-flex w-full overflow-hidden rounded-lg border border-slate-200 dark:border-slate-700"
|
||||
role="radiogroup"
|
||||
aria-label="字体大小"
|
||||
>
|
||||
<button
|
||||
v-for="opt in fontSizeOptions"
|
||||
:key="opt.value"
|
||||
type="button"
|
||||
role="radio"
|
||||
:aria-checked="fontSize === opt.value"
|
||||
class="flex-1 px-2 py-1.5 text-xs font-medium transition-colors"
|
||||
:class="
|
||||
fontSize === opt.value
|
||||
? 'bg-brand text-white'
|
||||
: 'bg-white text-slate-500 hover:bg-slate-100 dark:bg-slate-700 dark:text-slate-400 dark:hover:bg-slate-600'
|
||||
"
|
||||
@click="selectFontSize(opt.value)"
|
||||
>
|
||||
{{ opt.label }}
|
||||
</button>
|
||||
</div>
|
||||
<p
|
||||
class="mt-2 text-[11px] text-slate-400 dark:text-slate-500"
|
||||
>
|
||||
预览:星火应用商店 Spark Store 123
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 底部提示 -->
|
||||
@@ -185,6 +235,12 @@ import {
|
||||
setTagPriorityStrategy,
|
||||
type TagPriorityStrategy,
|
||||
} from "../global/tagPriority";
|
||||
import {
|
||||
getFontSize,
|
||||
setFontSize,
|
||||
FONT_SIZE_OPTIONS,
|
||||
type FontSizeOption,
|
||||
} from "../global/displaySettings";
|
||||
|
||||
const props = defineProps<{
|
||||
show: boolean;
|
||||
@@ -206,6 +262,9 @@ const strategyOptions: Array<{ value: TagPriorityStrategy; label: string }> = [
|
||||
{ value: "apm", label: "APM 优先" },
|
||||
];
|
||||
|
||||
// 字体大小档位选项(小 / 标准 / 大 / 特大)
|
||||
const fontSizeOptions = FONT_SIZE_OPTIONS;
|
||||
|
||||
const tagPriorityStrategy = ref<TagPriorityStrategy>("auto");
|
||||
|
||||
// 加载标签优先显示策略(从持久化读取)
|
||||
@@ -219,6 +278,19 @@ const selectStrategy = (value: TagPriorityStrategy) => {
|
||||
setTagPriorityStrategy(value);
|
||||
};
|
||||
|
||||
// 字体大小档位(仅字号,不含整体缩放/字体族)
|
||||
const fontSize = ref<FontSizeOption>("medium");
|
||||
|
||||
const loadFontSize = () => {
|
||||
fontSize.value = getFontSize();
|
||||
};
|
||||
|
||||
// 选择并保存字号档位(立即应用到 html,全局 rem 字号类联动)
|
||||
const selectFontSize = (value: FontSizeOption) => {
|
||||
fontSize.value = value;
|
||||
setFontSize(value);
|
||||
};
|
||||
|
||||
const settings = ref<Settings>({
|
||||
enableUpdateCheck: true,
|
||||
enableCreateDesktop: true,
|
||||
@@ -279,6 +351,7 @@ watch(
|
||||
if (newVal) {
|
||||
loadSettings();
|
||||
loadTagPriority();
|
||||
loadFontSize();
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
/**
|
||||
* 显示设置:全局字体大小档位(仅字号,不含整体缩放/字体族)。
|
||||
*
|
||||
* 实现原理:Tailwind 4 的 `text-*` 字号类均为 rem 单位(如 text-sm = 0.875rem),
|
||||
* 因此修改根元素 `html` 的 font-size 即可让全部 rem 字号类联动缩放。
|
||||
* 取值范围:14px(小) ~ 18px(特大),默认 16px(标准)。
|
||||
*
|
||||
* 持久化:localStorage key = "spark-store-font-size",存档位枚举字符串。
|
||||
*/
|
||||
export type FontSizeOption = "small" | "medium" | "large" | "xlarge";
|
||||
|
||||
interface FontSizeMeta {
|
||||
/** 应用到 html 的 font-size(px) */
|
||||
px: number;
|
||||
label: string;
|
||||
}
|
||||
|
||||
export const FONT_SIZE_OPTIONS: Array<{
|
||||
value: FontSizeOption;
|
||||
label: string;
|
||||
}> = [
|
||||
{ value: "small", label: "小" },
|
||||
{ value: "medium", label: "标准" },
|
||||
{ value: "large", label: "大" },
|
||||
{ value: "xlarge", label: "特大" },
|
||||
];
|
||||
|
||||
// 各档位对应的根字号。medium 保持现状 16px,向上放大、向下略缩。
|
||||
const FONT_SIZE_MAP: Record<FontSizeOption, FontSizeMeta> = {
|
||||
small: { px: 15, label: "小" },
|
||||
medium: { px: 16, label: "标准" },
|
||||
large: { px: 17, label: "大" },
|
||||
xlarge: { px: 18, label: "特大" },
|
||||
};
|
||||
|
||||
const FONT_SIZE_STORAGE_KEY = "spark-store-font-size";
|
||||
const DEFAULT_FONT_SIZE: FontSizeOption = "medium";
|
||||
|
||||
const isValidFontSize = (v: unknown): v is FontSizeOption =>
|
||||
typeof v === "string" && v in FONT_SIZE_MAP;
|
||||
|
||||
/** 读取持久化的字号档位(无/非法时回退默认「标准」) */
|
||||
export const getFontSize = (): FontSizeOption => {
|
||||
try {
|
||||
const raw = localStorage.getItem(FONT_SIZE_STORAGE_KEY);
|
||||
if (isValidFontSize(raw)) return raw;
|
||||
} catch {
|
||||
// localStorage 不可用时忽略,使用默认
|
||||
}
|
||||
return DEFAULT_FONT_SIZE;
|
||||
};
|
||||
|
||||
/** 将字号档位应用到根元素 html(写入 inline font-size) */
|
||||
export const applyFontSize = (option: FontSizeOption): void => {
|
||||
const meta = FONT_SIZE_MAP[option] ?? FONT_SIZE_MAP[DEFAULT_FONT_SIZE];
|
||||
document.documentElement.style.fontSize = `${meta.px}px`;
|
||||
};
|
||||
|
||||
/** 选择并持久化字号档位,同时立即应用 */
|
||||
export const setFontSize = (option: FontSizeOption): void => {
|
||||
applyFontSize(option);
|
||||
try {
|
||||
localStorage.setItem(FONT_SIZE_STORAGE_KEY, option);
|
||||
} catch {
|
||||
// 持久化失败时仍已应用当前会话,忽略写入错误
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 应用启动时初始化:从持久化恢复并使用,避免渲染瞬间闪烁。
|
||||
* 应在 App.vue 的 onMounted 最前调用(与 initTagPriorityStrategy 同级)。
|
||||
*/
|
||||
export const initFontSize = (): void => {
|
||||
applyFontSize(getFontSize());
|
||||
};
|
||||
Reference in New Issue
Block a user