Skip to content

Commit a88af61

Browse files
committed
🎈 perf: 字体配置独立
1 parent cbb63a0 commit a88af61

6 files changed

Lines changed: 241 additions & 156 deletions

File tree

components.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ declare module 'vue' {
2828
DownloadModal: typeof import('./src/components/Modal/DownloadModal.vue')['default']
2929
Equalizer: typeof import('./src/components/Modal/Equalizer.vue')['default']
3030
ExcludeLyrics: typeof import('./src/components/Modal/Setting/ExcludeLyrics.vue')['default']
31+
FontManager: typeof import('./src/components/Modal/Setting/FontManager.vue')['default']
3132
FullPlayer: typeof import('./src/components/Player/FullPlayer.vue')['default']
3233
GeneralSetting: typeof import('./src/components/Setting/GeneralSetting.vue')['default']
3334
HomePageSectionManager: typeof import('./src/components/Modal/Setting/HomePageSectionManager.vue')['default']
Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
<template>
2+
<div class="font-manager">
3+
<div class="set-list">
4+
<n-h3 prefix="bar">通用字体</n-h3>
5+
<n-card class="set-item">
6+
<div class="label">
7+
<n-text class="name">自定义 CSS 字体</n-text>
8+
<n-text class="tip" :depth="3"> 开启后可手动输入字体名称,支持 CSS 字体族 </n-text>
9+
</div>
10+
<n-switch v-model:value="settingStore.useCustomFont" class="set" :round="false" />
11+
</n-card>
12+
<n-card class="set-item">
13+
<div class="label">
14+
<n-text class="name">全局字体</n-text>
15+
<n-text class="tip" :depth="3">应用到软件内所有非特定区域的字体</n-text>
16+
</div>
17+
<n-flex align="center">
18+
<Transition name="fade" mode="out-in">
19+
<n-button
20+
v-if="settingStore.globalFont !== 'default'"
21+
type="primary"
22+
strong
23+
secondary
24+
@click="settingStore.globalFont = 'default'"
25+
>
26+
恢复默认
27+
</n-button>
28+
</Transition>
29+
<n-input
30+
v-if="settingStore.useCustomFont"
31+
v-model:value="settingStore.globalFont"
32+
placeholder="输入字体名称,例如: 'Microsoft YaHei'"
33+
class="set"
34+
/>
35+
<n-select
36+
v-else
37+
v-model:value="settingStore.globalFont"
38+
:options="getOptions('globalFont')"
39+
class="set"
40+
filterable
41+
/>
42+
</n-flex>
43+
</n-card>
44+
</div>
45+
46+
<div class="set-list">
47+
<n-h3 prefix="bar">歌词字体</n-h3>
48+
<n-card v-for="font in lyricFontConfigs" :key="font.key" class="set-item">
49+
<div class="label">
50+
<n-text class="name">{{ font.name }}</n-text>
51+
<n-text class="tip" :depth="3">{{ font.tip }}</n-text>
52+
</div>
53+
<n-flex align="center">
54+
<Transition name="fade" mode="out-in">
55+
<n-button
56+
v-if="settingStore[font.key] !== font.default"
57+
type="primary"
58+
strong
59+
secondary
60+
@click="settingStore[font.key] = font.default"
61+
>
62+
恢复默认
63+
</n-button>
64+
</Transition>
65+
<n-input
66+
v-if="settingStore.useCustomFont"
67+
v-model:value="settingStore[font.key]"
68+
placeholder="输入字体名称"
69+
class="set"
70+
/>
71+
<n-select
72+
v-else
73+
v-model:value="settingStore[font.key]"
74+
:options="getOptions(font.key)"
75+
class="set"
76+
filterable
77+
/>
78+
</n-flex>
79+
</n-card>
80+
</div>
81+
</div>
82+
</template>
83+
84+
<script setup lang="ts">
85+
import { useSettingStore } from "@/stores";
86+
import { isElectron } from "@/utils/env";
87+
import type { SelectOption } from "naive-ui";
88+
89+
const settingStore = useSettingStore();
90+
91+
interface FontConfig {
92+
name: string;
93+
key: "globalFont" | "LyricFont" | "japaneseLyricFont" | "englishLyricFont" | "koreanLyricFont";
94+
default: string;
95+
tip: string;
96+
}
97+
98+
const lyricFontConfigs: FontConfig[] = [
99+
{
100+
name: "歌词区域字体",
101+
key: "LyricFont",
102+
default: "follow",
103+
tip: "主歌词区域的基础字体",
104+
},
105+
{
106+
name: "英语歌词字体",
107+
key: "englishLyricFont",
108+
default: "follow",
109+
tip: "当歌词包含英语时使用的特定字体",
110+
},
111+
{
112+
name: "日语歌词字体",
113+
key: "japaneseLyricFont",
114+
default: "follow",
115+
tip: "当歌词包含日语时使用的特定字体",
116+
},
117+
{
118+
name: "韩语歌词字体",
119+
key: "koreanLyricFont",
120+
default: "follow",
121+
tip: "当歌词包含韩语时使用的特定字体",
122+
},
123+
];
124+
125+
// 系统字体选项
126+
const systemFonts = ref<SelectOption[]>([]);
127+
128+
// 获取下拉选项
129+
const getOptions = (key: string) => {
130+
const isGlobal = key === "globalFont";
131+
const defaultLabel = isGlobal ? "系统默认" : "跟随全局";
132+
const defaultValue = isGlobal ? "default" : "follow";
133+
134+
return [{ label: defaultLabel, value: defaultValue }, ...systemFonts.value];
135+
};
136+
137+
// 获取全部系统字体
138+
const getAllSystemFonts = async () => {
139+
if (!isElectron) return;
140+
try {
141+
const allFonts = await window.electron.ipcRenderer.invoke("get-all-fonts");
142+
systemFonts.value = allFonts.map((v: string) => {
143+
const name = v.replace(/^['"]+|['"]+$/g, "");
144+
return {
145+
label: name,
146+
value: name,
147+
style: {
148+
fontFamily: name,
149+
},
150+
};
151+
});
152+
} catch (error) {
153+
console.error("Failed to get system fonts:", error);
154+
}
155+
};
156+
157+
onMounted(() => {
158+
getAllSystemFonts();
159+
});
160+
</script>
161+
162+
<style lang="scss" scoped>
163+
.font-manager {
164+
padding: 4px;
165+
.set-list {
166+
margin-bottom: 24px;
167+
&:last-child {
168+
margin-bottom: 0;
169+
}
170+
}
171+
172+
.set-item {
173+
width: 100%;
174+
border-radius: 8px;
175+
margin-bottom: 12px;
176+
transition: margin 0.3s;
177+
&:last-child {
178+
margin-bottom: 0;
179+
}
180+
:deep(.n-card__content) {
181+
display: flex;
182+
flex-direction: row;
183+
align-items: center;
184+
justify-content: space-between;
185+
padding: 16px;
186+
}
187+
.label {
188+
display: flex;
189+
flex-direction: column;
190+
padding-right: 20px;
191+
.name {
192+
font-size: 16px;
193+
}
194+
}
195+
.n-flex {
196+
flex-flow: nowrap !important;
197+
}
198+
.set {
199+
justify-content: flex-end;
200+
width: 200px;
201+
&.n-switch {
202+
width: max-content;
203+
}
204+
@media (max-width: 768px) {
205+
width: 140px;
206+
min-width: 140px;
207+
}
208+
}
209+
}
210+
}
211+
</style>

src/components/Setting/GeneralSetting.vue

Lines changed: 4 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -190,28 +190,10 @@
190190
</n-card>
191191
<n-card class="set-item">
192192
<div class="label">
193-
<n-text class="name">自定义字体</n-text>
194-
<n-text class="tip" :depth="3"> 更改软件内全局字体 </n-text>
193+
<n-text class="name">字体设置</n-text>
194+
<n-text class="tip" :depth="3"> 统一配置全局及歌词区域的字体 </n-text>
195195
</div>
196-
<n-flex>
197-
<Transition name="fade" mode="out-in">
198-
<n-button
199-
v-if="settingStore.globalFont !== 'default'"
200-
type="primary"
201-
strong
202-
secondary
203-
@click="settingStore.globalFont = 'default'"
204-
>
205-
恢复默认
206-
</n-button>
207-
</Transition>
208-
<n-select
209-
v-model:value="settingStore.globalFont"
210-
:options="allFontsData"
211-
class="set"
212-
filterable
213-
/>
214-
</n-flex>
196+
<n-button type="primary" strong secondary @click="openFontManager"> 配置 </n-button>
215197
</n-card>
216198
<n-card class="set-item">
217199
<div class="label">
@@ -290,7 +272,7 @@ import { useDataStore, useMusicStore, useSettingStore, useStatusStore } from "@/
290272
import { isDev, isElectron } from "@/utils/env";
291273
import { isEmpty } from "lodash-es";
292274
import themeColor from "@/assets/data/themeColor.json";
293-
import { openSidebarHideManager, openHomePageSectionManager } from "@/utils/modal";
275+
import { openSidebarHideManager, openHomePageSectionManager, openFontManager } from "@/utils/modal";
294276
import { sendRegisterProtocol } from "@/utils/protocol";
295277
import { getCoverColor } from "@/utils/color";
296278
@@ -299,9 +281,6 @@ const musicStore = useMusicStore();
299281
const settingStore = useSettingStore();
300282
const statusStore = useStatusStore();
301283
302-
// 全部字体
303-
const allFontsData = ref<SelectOption[]>([]);
304-
305284
// 是否开启在线服务
306285
const useOnlineService = ref(settingStore.useOnlineService);
307286
@@ -322,31 +301,6 @@ const closeTaskbarProgress = (val: boolean) => {
322301
if (!val) window.electron.ipcRenderer.send("set-bar", "none");
323302
};
324303
325-
// 获取全部系统字体
326-
const getAllSystemFonts = async () => {
327-
const allFonts = await window.electron.ipcRenderer.invoke("get-all-fonts");
328-
allFonts.map((v: string) => {
329-
// 去除前后的引号
330-
v = v.replace(/^['"]+|['"]+$/g, "");
331-
allFontsData.value.push({
332-
label: v,
333-
value: v,
334-
style: {
335-
fontFamily: v,
336-
},
337-
});
338-
});
339-
// 添加默认选项
340-
allFontsData.value.unshift({
341-
label: "系统默认",
342-
value: "default",
343-
style: {
344-
fontFamily:
345-
"v-sans, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'",
346-
},
347-
});
348-
};
349-
350304
// 在线模式切换
351305
const modeChange = (val: boolean) => {
352306
if (val) {
@@ -404,10 +358,4 @@ const themeGlobalColorChange = (val: boolean) => {
404358
const orpheusChange = async (isRegistry: boolean) => {
405359
sendRegisterProtocol("orpheus", isRegistry);
406360
};
407-
408-
onMounted(() => {
409-
if (isElectron) {
410-
getAllSystemFonts();
411-
}
412-
});
413361
</script>

0 commit comments

Comments
 (0)