feat: 编辑器亮色/暗色主题切换 + 保存到MySQL
- 标题栏🌙/☀️按钮切换 Monaco 主题 - 'vs'(亮色) / 'vs-dark'(暗色) - 切换后立即应用到所有打开的标签页 - 通过 PUT /api/settings/editor_theme 保存到MySQL - 页面加载时自动读取保存的主题偏好 - settings.py MUTABLE_KEYS 白名单加 editor_theme
This commit is contained in:
@@ -45,6 +45,7 @@ MUTABLE_KEYS: set[str] = {
|
|||||||
"notify_alert_cpu", "notify_alert_mem", "notify_alert_disk",
|
"notify_alert_cpu", "notify_alert_mem", "notify_alert_disk",
|
||||||
"notify_recovery", "notify_time_drift",
|
"notify_recovery", "notify_time_drift",
|
||||||
"notify_system_redis", "notify_system_mysql", "notify_restart",
|
"notify_system_redis", "notify_system_mysql", "notify_restart",
|
||||||
|
"editor_theme", # Monaco editor theme preference
|
||||||
}
|
}
|
||||||
|
|
||||||
# S-02: Per-key validation rules: (type, min, max) for int settings
|
# S-02: Per-key validation rules: (type, min, max) for int settings
|
||||||
|
|||||||
+25
-1
@@ -71,6 +71,7 @@
|
|||||||
<div id="editorTabBar" class="flex flex-1 overflow-x-auto min-w-0"></div>
|
<div id="editorTabBar" class="flex flex-1 overflow-x-auto min-w-0"></div>
|
||||||
<!-- Right buttons -->
|
<!-- Right buttons -->
|
||||||
<div class="flex items-center shrink-0">
|
<div class="flex items-center shrink-0">
|
||||||
|
<button onclick="toggleEditorTheme()" id="themeBtn" class="text-slate-500 hover:text-white px-2 py-2 text-sm hover:bg-slate-700" title="切换亮色/暗色主题">🌙</button>
|
||||||
<button onclick="toggleEditorSize()" id="sizeBtn" class="text-slate-500 hover:text-white px-2 py-2 text-sm hover:bg-slate-700" title="最大化/还原">⬜</button>
|
<button onclick="toggleEditorSize()" id="sizeBtn" class="text-slate-500 hover:text-white px-2 py-2 text-sm hover:bg-slate-700" title="最大化/还原">⬜</button>
|
||||||
<button onclick="toggleEditorFullscreen()" id="fsBtn" class="text-slate-500 hover:text-white px-2 py-2 text-sm hover:bg-slate-700" title="全屏">⤢</button>
|
<button onclick="toggleEditorFullscreen()" id="fsBtn" class="text-slate-500 hover:text-white px-2 py-2 text-sm hover:bg-slate-700" title="全屏">⤢</button>
|
||||||
<button onclick="minimizeEditor()" class="text-slate-500 hover:text-white px-2 py-2 text-sm hover:bg-slate-700" title="最小化">—</button>
|
<button onclick="minimizeEditor()" class="text-slate-500 hover:text-white px-2 py-2 text-sm hover:bg-slate-700" title="最小化">—</button>
|
||||||
@@ -636,6 +637,29 @@
|
|||||||
let _activeTab=-1;
|
let _activeTab=-1;
|
||||||
let _editorVisible=false;
|
let _editorVisible=false;
|
||||||
let _editorMinimized=false;
|
let _editorMinimized=false;
|
||||||
|
let _editorTheme='vs'; // 'vs' (light) or 'vs-dark' (dark)
|
||||||
|
|
||||||
|
// Load editor theme from settings
|
||||||
|
async function loadEditorTheme(){
|
||||||
|
try{
|
||||||
|
const r=await apiFetch(API+'/settings/editor_theme');
|
||||||
|
if(r&&r.ok){const d=await r.json();if(d.value&&d.value!=='null')_editorTheme=d.value}
|
||||||
|
}catch(e){}
|
||||||
|
updateThemeBtn();
|
||||||
|
}
|
||||||
|
loadEditorTheme();
|
||||||
|
|
||||||
|
function updateThemeBtn(){
|
||||||
|
const btn=document.getElementById('themeBtn');
|
||||||
|
if(btn)btn.textContent=_editorTheme==='vs-dark'?'🌙':'☀️';
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleEditorTheme(){
|
||||||
|
_editorTheme=_editorTheme==='vs'?'vs-dark':'vs';
|
||||||
|
_openTabs.forEach(t=>{if(t.editor)t.editor.updateOptions({theme:_editorTheme})});
|
||||||
|
updateThemeBtn();
|
||||||
|
apiFetch(API+'/settings/editor_theme',{method:'PUT',headers:apiHeadersJSON(),body:JSON.stringify({value:_editorTheme})});
|
||||||
|
}
|
||||||
|
|
||||||
function openFileInEditor(path,name,content){
|
function openFileInEditor(path,name,content){
|
||||||
// Check if already open
|
// Check if already open
|
||||||
@@ -654,7 +678,7 @@
|
|||||||
if(window._monacoReady){
|
if(window._monacoReady){
|
||||||
tab.editor=monaco.editor.create(container,{
|
tab.editor=monaco.editor.create(container,{
|
||||||
value:content,language:lang,
|
value:content,language:lang,
|
||||||
// 官方默认配置 — 不匹配项目主题
|
theme:_editorTheme,
|
||||||
automaticLayout:true,
|
automaticLayout:true,
|
||||||
lineNumbers:'on',folding:true,
|
lineNumbers:'on',folding:true,
|
||||||
bracketPairColorization:{enabled:true},matchBrackets:'always',
|
bracketPairColorization:{enabled:true},matchBrackets:'always',
|
||||||
|
|||||||
Reference in New Issue
Block a user