From 94cbcef32485598c9ec6e11c02e34af0847ce60f Mon Sep 17 00:00:00 2001
From: Ap_Tx <3045929398@qq.com>
Date: Wed, 30 Sep 2026 22:40:24 +0800
Subject: [PATCH] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=E5=90=AF=E5=8A=A8?=
=?UTF-8?q?=E5=99=A8=E7=95=8C=E9=9D=A2=E7=BC=A9=E6=94=BE=E8=AE=BE=E7=BD=AE?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
在高缩放/小屏下,内嵌网页(如皮肤站)顶栏会被裁掉。新增“界面
与外观”中的“启动器缩放”设置,可整体缩放启动器界面。
- 新增 helpers/ui-scale.ts:用 localStorage 保存缩放值(纯本地
显示偏好,无需后端),并通过 CSS zoom 应用缩放(含内嵌网页)。
- App.vue 启动时调用 installUiScale() 应用已保存的缩放。
- AppearanceSettings.vue 新增缩放设置项:100/110/125/150 预设
加 50–200 滑条自定义。
---
apps/app-frontend/src/App.vue | 3 +
.../ui/settings/AppearanceSettings.vue | 55 +++++++++++++++++
apps/app-frontend/src/helpers/ui-scale.ts | 60 +++++++++++++++++++
3 files changed, 118 insertions(+)
create mode 100644 apps/app-frontend/src/helpers/ui-scale.ts
diff --git a/apps/app-frontend/src/App.vue b/apps/app-frontend/src/App.vue
index bc43254..3c07d15 100644
--- a/apps/app-frontend/src/App.vue
+++ b/apps/app-frontend/src/App.vue
@@ -141,6 +141,7 @@ import {
isNetworkMetered,
setRestartAfterPendingUpdate,
} from '@/helpers/utils.js'
+import { installUiScale } from '@/helpers/ui-scale'
import { start_join_server, start_join_singleplayer_world } from '@/helpers/worlds.ts'
import i18n, { resolveInitialLocale } from '@/i18n.config'
import {
@@ -1273,6 +1274,8 @@ provide('previewMinecraftCrashModal', () => minecraftCrashModal.value?.showPrevi
provide('showLauncherPopup', (_request: unknown) => {})
provide('showStartupAnnouncement', () => startupAnnouncementModal.value?.show())
+installUiScale()
+
const stateFailed = ref(false)
stateInitialization
.then(() => {
diff --git a/apps/app-frontend/src/components/ui/settings/AppearanceSettings.vue b/apps/app-frontend/src/components/ui/settings/AppearanceSettings.vue
index c6ff9f8..506a848 100644
--- a/apps/app-frontend/src/components/ui/settings/AppearanceSettings.vue
+++ b/apps/app-frontend/src/components/ui/settings/AppearanceSettings.vue
@@ -26,6 +26,7 @@ import { computed, ref, watch } from 'vue'
import { get, set } from '@/helpers/settings.ts'
import { getOS } from '@/helpers/utils'
+import { setUiScale, uiScale } from '@/helpers/ui-scale'
import { useTheming } from '@/store/state'
import {
type AccentColor,
@@ -209,6 +210,23 @@ const messages = defineMessages({
defaultMessage:
'Enables advanced rendering such as blur effects that may cause performance issues without hardware-accelerated rendering.',
},
+ uiScaleTitle: {
+ id: 'app.appearance-settings.ui-scale.title',
+ defaultMessage: 'Launcher scale',
+ },
+ uiScaleDescription: {
+ id: 'app.appearance-settings.ui-scale.description',
+ defaultMessage:
+ 'Scale the whole launcher interface. A smaller scale fits more content, which helps when embedded pages are cut off.',
+ },
+ uiScaleCustom: {
+ id: 'app.appearance-settings.ui-scale.custom',
+ defaultMessage: 'Custom',
+ },
+ uiScalePercent: {
+ id: 'app.appearance-settings.ui-scale.percent',
+ defaultMessage: '{value}%',
+ },
pageTransitionsTitle: {
id: 'app.appearance-settings.page-transitions.title',
defaultMessage: 'Page transition animations',
@@ -1020,6 +1038,43 @@ watch(
/>
+
+
+
+ {{ formatMessage(messages.uiScaleTitle) }}
+
+
+ {{ formatMessage(messages.uiScaleDescription) }}
+
+
+
+
+
+
setUiScale(Number(value))"
+ />
+
+
+
diff --git a/apps/app-frontend/src/helpers/ui-scale.ts b/apps/app-frontend/src/helpers/ui-scale.ts
new file mode 100644
index 0000000..1e606eb
--- /dev/null
+++ b/apps/app-frontend/src/helpers/ui-scale.ts
@@ -0,0 +1,60 @@
+import { ref, watch } from 'vue'
+
+/**
+ * 启动器界面缩放(百分比)。
+ * 这是纯本地的显示偏好,用 localStorage 保存即可,无需写入后端设置数据库。
+ */
+const UI_SCALE_STORAGE_KEY = 'starlight-ui-scale'
+const MIN_UI_SCALE = 50
+const MAX_UI_SCALE = 200
+const DEFAULT_UI_SCALE = 100
+
+/** 把缩放值限制在允许范围内。 */
+function clampUiScale(value: number): number {
+ if (!Number.isFinite(value)) return DEFAULT_UI_SCALE
+ return Math.min(MAX_UI_SCALE, Math.max(MIN_UI_SCALE, Math.round(value)))
+}
+
+/** 从 localStorage 读取已保存的缩放值。 */
+function readStoredUiScale(): number {
+ try {
+ const raw = localStorage.getItem(UI_SCALE_STORAGE_KEY)
+ if (raw === null) return DEFAULT_UI_SCALE
+ return clampUiScale(Number(raw))
+ } catch {
+ return DEFAULT_UI_SCALE
+ }
+}
+
+export const uiScale = ref(readStoredUiScale())
+
+export function setUiScale(value: number): void {
+ uiScale.value = clampUiScale(value)
+}
+
+export function resetUiScale(): void {
+ setUiScale(DEFAULT_UI_SCALE)
+}
+
+export { DEFAULT_UI_SCALE, MAX_UI_SCALE, MIN_UI_SCALE }
+
+/** 把缩放应用到文档根节点,并在变化时持久化。 */
+export function installUiScale(): void {
+ const apply = (value: number) => {
+ const factor = String(value / 100)
+ const root = document.documentElement
+ root.style.setProperty('--ui-scale', factor)
+ // 用 CSS zoom 整体缩放界面(含内嵌网页),在 WebView2/WebKit 上最可靠。
+ root.style.setProperty('zoom', factor)
+ }
+
+ apply(uiScale.value)
+ watch(uiScale, (value) => {
+ apply(value)
+ try {
+ localStorage.setItem(UI_SCALE_STORAGE_KEY, String(value))
+ } catch (error) {
+ console.warn('保存界面缩放失败', error)
+ }
+ })
+}
\ No newline at end of file