feat(字体): 添加应用字体和代码字体自定义功能
- 在设置面板中新增应用字体和代码字体选择器 - 支持霞鹜文楷、思源宋体、站酷快乐体等多种中文字体 - 代码编辑器支持 Fira Code 等编程字体 - 通过 CSS 变量动态切换字体,确保界面一致性
This commit is contained in:
parent
d774524881
commit
ef33564e99
|
|
@ -5,7 +5,9 @@
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@300;400;500;700&display=swap" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@300;400;500;700&family=Fira+Code:wght@400;500&family=Noto+Serif+SC:wght@400;700&family=ZCOOL+KuaiLe&display=swap" rel="stylesheet">
|
||||||
|
<!-- 引入霞鹜文楷 -->
|
||||||
|
<link rel="stylesheet" href="https://npm.elemecdn.com/lxgw-wenkai-screen-web/style.css" media="print" onload="this.media='all'">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
|
|
|
||||||
29
src/App.vue
29
src/App.vue
|
|
@ -14,7 +14,18 @@ import { SettingOutlined } from '@ant-design/icons-vue';
|
||||||
|
|
||||||
const { setRootPath } = useFileTree();
|
const { setRootPath } = useFileTree();
|
||||||
const { loadConfig } = useConfig();
|
const { loadConfig } = useConfig();
|
||||||
const { getAntdTheme, primaryColor, toggleTheme, isDark, toggleDarkMode, setGlobalTheme } = useTheme();
|
const {
|
||||||
|
getAntdTheme,
|
||||||
|
primaryColor,
|
||||||
|
toggleTheme,
|
||||||
|
isDark,
|
||||||
|
toggleDarkMode,
|
||||||
|
setGlobalTheme,
|
||||||
|
fontFamily,
|
||||||
|
codeFontFamily,
|
||||||
|
setFontFamily,
|
||||||
|
setCodeFontFamily
|
||||||
|
} = useTheme();
|
||||||
|
|
||||||
const route = ref("");
|
const route = ref("");
|
||||||
const showSearch = ref(false);
|
const showSearch = ref(false);
|
||||||
|
|
@ -271,6 +282,22 @@ const { state } = useFileTree(); // 需要获取 rootPath 用于保存
|
||||||
<div class="settings-label">暗黑模式</div>
|
<div class="settings-label">暗黑模式</div>
|
||||||
<a-switch v-model:checked="isDark" @change="toggleDarkMode" />
|
<a-switch v-model:checked="isDark" @change="toggleDarkMode" />
|
||||||
</div>
|
</div>
|
||||||
|
<div class="settings-item">
|
||||||
|
<div class="settings-label">应用字体</div>
|
||||||
|
<a-select :value="fontFamily" style="width: 100%" @change="setFontFamily">
|
||||||
|
<a-select-option value="default">系统默认</a-select-option>
|
||||||
|
<a-select-option value="lxgw">霞鹜文楷 (LXGW WenKai)</a-select-option>
|
||||||
|
<a-select-option value="serif">思源宋体 (Noto Serif)</a-select-option>
|
||||||
|
<a-select-option value="zcool">站酷快乐体 (演示用)</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
</div>
|
||||||
|
<div class="settings-item">
|
||||||
|
<div class="settings-label">代码字体</div>
|
||||||
|
<a-select :value="codeFontFamily" style="width: 100%" @change="setCodeFontFamily">
|
||||||
|
<a-select-option value="default">系统默认 (Monospace)</a-select-option>
|
||||||
|
<a-select-option value="fira">Fira Code</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
</div>
|
||||||
</a-modal>
|
</a-modal>
|
||||||
|
|
||||||
<!-- 历史记录弹窗 -->
|
<!-- 历史记录弹窗 -->
|
||||||
|
|
|
||||||
|
|
@ -49,16 +49,13 @@ let detachPaste = null
|
||||||
let removeActionListener = null
|
let removeActionListener = null
|
||||||
|
|
||||||
const liveEditorTheme = computed(() => {
|
const liveEditorTheme = computed(() => {
|
||||||
const contentFont = '-apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif'
|
|
||||||
const monospaceFont = 'SFMono-Regular, Consolas, "Liberation Mono", Menlo, monospace'
|
|
||||||
|
|
||||||
return EditorView.theme({
|
return EditorView.theme({
|
||||||
'&': {
|
'&': {
|
||||||
backgroundColor: 'var(--card-background)',
|
backgroundColor: 'var(--card-background)',
|
||||||
color: 'var(--text-color)'
|
color: 'var(--text-color)'
|
||||||
},
|
},
|
||||||
'.cm-scroller': {
|
'.cm-scroller': {
|
||||||
fontFamily: contentFont
|
fontFamily: 'var(--app-font-family)'
|
||||||
},
|
},
|
||||||
'.cm-content': {
|
'.cm-content': {
|
||||||
padding: '30px 40px',
|
padding: '30px 40px',
|
||||||
|
|
@ -67,6 +64,8 @@ const liveEditorTheme = computed(() => {
|
||||||
margin: '0 auto',
|
margin: '0 auto',
|
||||||
caretColor: 'var(--primary-color)'
|
caretColor: 'var(--primary-color)'
|
||||||
},
|
},
|
||||||
|
// ... 其他保持不变,但需要确保 monospaceFont 的地方也改了
|
||||||
|
|
||||||
'.cm-selectionBackground, ::selection': {
|
'.cm-selectionBackground, ::selection': {
|
||||||
backgroundColor: 'var(--primary-color-bg)'
|
backgroundColor: 'var(--primary-color-bg)'
|
||||||
},
|
},
|
||||||
|
|
@ -138,7 +137,7 @@ const liveEditorTheme = computed(() => {
|
||||||
|
|
||||||
// 行内代码样式
|
// 行内代码样式
|
||||||
'.cm-md-monospace': {
|
'.cm-md-monospace': {
|
||||||
fontFamily: monospaceFont,
|
fontFamily: 'var(--editor-font-family)',
|
||||||
backgroundColor: 'var(--hover-background)',
|
backgroundColor: 'var(--hover-background)',
|
||||||
padding: '2px 4px',
|
padding: '2px 4px',
|
||||||
borderRadius: '4px',
|
borderRadius: '4px',
|
||||||
|
|
@ -147,7 +146,7 @@ const liveEditorTheme = computed(() => {
|
||||||
|
|
||||||
// 代码块样式
|
// 代码块样式
|
||||||
'.cm-line.cm-md-fenced-code': {
|
'.cm-line.cm-md-fenced-code': {
|
||||||
fontFamily: monospaceFont,
|
fontFamily: 'var(--editor-font-family)',
|
||||||
backgroundColor: 'var(--hover-background)',
|
backgroundColor: 'var(--hover-background)',
|
||||||
paddingLeft: '16px',
|
paddingLeft: '16px',
|
||||||
fontSize: '0.9em'
|
fontSize: '0.9em'
|
||||||
|
|
@ -160,7 +159,7 @@ const liveEditorTheme = computed(() => {
|
||||||
'.cm-md-code-info': {
|
'.cm-md-code-info': {
|
||||||
opacity: 0.5,
|
opacity: 0.5,
|
||||||
fontSize: '0.85em',
|
fontSize: '0.85em',
|
||||||
fontFamily: contentFont,
|
fontFamily: 'var(--app-font-family)',
|
||||||
float: 'right',
|
float: 'right',
|
||||||
marginRight: '8px'
|
marginRight: '8px'
|
||||||
},
|
},
|
||||||
|
|
@ -186,7 +185,7 @@ const liveEditorTheme = computed(() => {
|
||||||
},
|
},
|
||||||
// 表格源码编辑时的样式
|
// 表格源码编辑时的样式
|
||||||
'.cm-line.cm-md-table-source': {
|
'.cm-line.cm-md-table-source': {
|
||||||
fontFamily: monospaceFont,
|
fontFamily: 'var(--editor-font-family)',
|
||||||
whiteSpace: 'pre'
|
whiteSpace: 'pre'
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,8 @@ import { theme } from 'ant-design-vue';
|
||||||
|
|
||||||
const primaryColor = ref('#1890ff');
|
const primaryColor = ref('#1890ff');
|
||||||
const isDark = ref(false);
|
const isDark = ref(false);
|
||||||
|
const fontFamily = ref('default');
|
||||||
|
const codeFontFamily = ref('default');
|
||||||
|
|
||||||
export function useTheme() {
|
export function useTheme() {
|
||||||
const toggleTheme = (color) => {
|
const toggleTheme = (color) => {
|
||||||
|
|
@ -15,15 +17,41 @@ export function useTheme() {
|
||||||
updateCSSVariables();
|
updateCSSVariables();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const setFontFamily = (font) => {
|
||||||
|
fontFamily.value = font;
|
||||||
|
updateCSSVariables();
|
||||||
|
};
|
||||||
|
|
||||||
|
const setCodeFontFamily = (font) => {
|
||||||
|
codeFontFamily.value = font;
|
||||||
|
updateCSSVariables();
|
||||||
|
};
|
||||||
|
|
||||||
const updateCSSVariables = () => {
|
const updateCSSVariables = () => {
|
||||||
const root = document.documentElement;
|
const root = document.documentElement;
|
||||||
root.dataset.theme = isDark.value ? 'dark' : 'light';
|
root.dataset.theme = isDark.value ? 'dark' : 'light';
|
||||||
root.style.setProperty('--primary-color', primaryColor.value);
|
root.style.setProperty('--primary-color', primaryColor.value);
|
||||||
|
|
||||||
// 生成一个浅色背景用于选中态
|
// 生成一个浅色背景用于选中态
|
||||||
// 简单变淡处理,或者直接使用 opacity
|
|
||||||
root.style.setProperty('--primary-color-bg', primaryColor.value + '1A'); // 10% opacity
|
root.style.setProperty('--primary-color-bg', primaryColor.value + '1A'); // 10% opacity
|
||||||
|
|
||||||
|
// 字体设置
|
||||||
|
let fontValue = '-apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif';
|
||||||
|
if (fontFamily.value === 'lxgw') {
|
||||||
|
fontValue = '"LXGW WenKai Screen", sans-serif';
|
||||||
|
} else if (fontFamily.value === 'serif') {
|
||||||
|
fontValue = '"Noto Serif SC", serif';
|
||||||
|
} else if (fontFamily.value === 'zcool') {
|
||||||
|
fontValue = '"ZCOOL KuaiLe", cursive';
|
||||||
|
}
|
||||||
|
root.style.setProperty('--app-font-family', fontValue);
|
||||||
|
|
||||||
|
let codeFontValue = 'SFMono-Regular, Consolas, "Liberation Mono", Menlo, monospace';
|
||||||
|
if (codeFontFamily.value === 'fira') {
|
||||||
|
codeFontValue = '"Fira Code", monospace';
|
||||||
|
}
|
||||||
|
root.style.setProperty('--editor-font-family', codeFontValue);
|
||||||
|
|
||||||
if (isDark.value) {
|
if (isDark.value) {
|
||||||
root.style.setProperty('--app-background', '#141414');
|
root.style.setProperty('--app-background', '#141414');
|
||||||
root.style.setProperty('--card-background', '#1f1f1f');
|
root.style.setProperty('--card-background', '#1f1f1f');
|
||||||
|
|
@ -79,6 +107,10 @@ export function useTheme() {
|
||||||
toggleTheme,
|
toggleTheme,
|
||||||
toggleDarkMode,
|
toggleDarkMode,
|
||||||
getAntdTheme,
|
getAntdTheme,
|
||||||
setGlobalTheme
|
setGlobalTheme,
|
||||||
|
fontFamily,
|
||||||
|
codeFontFamily,
|
||||||
|
setFontFamily,
|
||||||
|
setCodeFontFamily
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue