Your Name
d93c518a14
feat(files): POSIX paths, elevation, recursive chmod, access hints and docs
...
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-01 19:54:18 +08:00
Your Name
1cfac23c01
feat: terminal ANSI colors and enhanced shell syntax highlighting
...
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-01 15:49:27 +08:00
Your Name
799140f6c4
feat: terminal SPA layout, route sync, and WebSocket URL helper
...
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-01 15:41:59 +08:00
Your Name
8935081ac5
feat: full-site acceptance automation and health/detail fix
...
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-01 15:22:42 +08:00
Your Name
ab431028c1
fix: 服务器页批量选择绑定 Vuetify4 modelValue
...
v-model:selected 无法同步勾选状态;生产已部署 ServersPage-CGp8DUVa.js 并验证「已选择 2 台服务器」。
2026-06-01 14:54:39 +08:00
Your Name
cc2dad7f31
docs: 生产浏览器验收 — SPA/WebSSH/health_monitor
...
详见 docs/reports/2026-06-01-browser-verification.md;批量条与 Telegram/Push/kill 留维护窗口或人工确认。
2026-06-01 14:20:45 +08:00
Your Name
24b4439b2b
docs: 单负责人执行计划 — handoff 对齐、生产验收、prune 加固
...
计划见 docs/design/plans/2026-06-01-single-owner-execution.md;生产 health/app/Redis/MySQL 已通过。
2026-06-01 14:09:17 +08:00
Your Name
b8af1fc418
chore: 移除 superpowers 工作流 Skill,改为单 Agent 协作
...
停用 .cursor/skills 与虚拟部门分派,新增 no-department-agents 规则并更新文档索引与验收标准。
2026-06-01 14:04:50 +08:00
Your Name
b77a314b36
chore: remove virtual department agent docs (team/skills)
...
Delete docs/skills/, docs/team/, and TEAM_ROLES.md. Update docs/README and mem_key_files. Standards and .cursor/skills workflows unchanged.
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-01 13:52:55 +08:00
Your Name
d519113734
fix: Gate3 health plain text, refresh empty body, prune underscore chunks
...
test_api: assert /health returns plain text ok instead of JSON parse.
auth: RefreshRequest.refresh_token optional so SPA POST {} is not 422.
prune: allow leading underscore in asset names to avoid deleting _plugin-vue_export-helper.
Add run_test_api_on_server.sh and deployment follow-up changelog.
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-01 13:41:28 +08:00
Your Name
65c77155d8
fix: 修复前端 assets 清理脚本以支持 Rolldown 产物
...
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-01 12:31:55 +08:00
Your Name
2deb89b49c
deploy: 前端部署后自动清理孤儿 assets + 冒烟脚本
...
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-01 12:29:57 +08:00
Your Name
b76295aaec
docs: 记录 2026-06-01 生产部署验证结果
...
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-01 12:23:44 +08:00
Your Name
8311821590
fix: 全量修复批量选择、JWT 60min、script-callback 认证与心跳数据流
...
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-01 12:17:47 +08:00
Your Name
73fdcafb81
docs: 完整交接文件 (15章节 + Cursor提示词 + 部署问题)
...
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-01 11:58:11 +08:00
Your Name
91d0d4104e
docs: 添加 .cursorrules 供 Cursor 接管
...
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-01 11:54:11 +08:00
Your Name
7fa4bd6dff
docs: Cursor交接文件 2026-06-01
...
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-01 11:49:12 +08:00
Your Name
a20cefcfbd
docs: 审计+changelog 全站bug审查修复
...
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-01 11:40:23 +08:00
Your Name
6183047fd6
fix: 全站 bug 审查修复 (前端9项 + 后端5项)
...
Nexus CI/CD / test (push) Waiting to run
Nexus CI/CD / deploy (push) Blocked by required conditions
Nexus Pre-commit Checks / quick-check (push) Waiting to run
前端修复:
- P0: App.vue http 未导入导致全局搜索崩溃
- P1: TOTP 登录流程断裂 (TotpRequiredError 非 ApiError 子类)
- P1: ServersPage 编辑服务器 domain 被端口字符串污染
- P1: PushPage Set[0] 无效 → values().next().value
- P1: SettingsPage API 返回字符串未转数字
- P2: api/index.ts getList 重复定义移除
- P2: LoginPage 锁定倒计时 now ref + watch 更新
- P2: TerminalPage 路径验证正则放松 (允许空格/中文)
- P2: useWebSocket CONNECTING/CLOSING 状态关闭旧连接
后端修复:
- P1: websocket.py redis.keys() → scan_iter() 避免阻塞
- P1: auth_service.py TTL 仅在 key 无 TTL 时设置
- P1: servers.py 批量操作加 asyncio.Lock 避免并发 session commit
- P2: settings.py asyncio.get_event_loop() → get_running_loop()
- P2: settings.py datetime.utcfromtimestamp() → datetime.fromtimestamp(tz=utc)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-01 11:24:55 +08:00
Your Name
df2c188f5d
docs: Cursor 交接文件
...
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-05-31 23:32:10 +08:00
Your Name
2d00d6a8eb
fix: 登录页居中布局 + 删除Logo区域
...
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-05-31 23:30:12 +08:00
Your Name
080c1158d4
docs: 审计文档 + changelog (TerminalPage迭代)
...
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-05-31 23:24:53 +08:00
Your Name
facc1e8ae4
feat: TerminalPage全面迭代 + 快捷命令MySQL持久化
...
P0: Ctrl+L清屏、命令历史恢复、重连per-session、onopen不忽略、ping per-session
P1: 空catch处理、termRefs用session.id、错误透传、剪贴板权限、webssh-token错误
P2: 全选菜单、指数退避重连、快捷命令编辑、uptime per-session
新功能: quick_commands MySQL表 + CRUD API、Shell语法高亮输入栏
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-05-31 23:12:18 +08:00
Your Name
1ecd8e4542
fix: move wallpaper routes before /{key} catch-all to fix 404
...
Bing wallpaper endpoint (/bing-wallpapers) was returning 404 from HTTP
because FastAPI matched it against the /{key} catch-all route at position
2 before the specific route at position 13 ever got reached.
- Moved wallpaper routes (bing-wallpapers, bing-wallpaper) and helper code
before the /{key} wildcard route
- Removed dead guard code in get_setting() that was never effective —
FastAPI route matching happens before the handler body executes
- Removed duplicate wallpaper code block at end of file
Root cause: FastAPI matches routes in registration order. /{key} at
position 2 matched 'bing-wallpapers' as the key parameter, returning
'Setting not found' instead of routing to the wallpaper endpoint.
2026-05-31 22:00:33 +08:00
Your Name
c6485168b6
fix: bing-wallpapers route was being caught by /{key} catch-all
...
FastAPI matches routes in order: /{key} registered before bing-wallpapers
because routes are sorted by path. /{key} matches 'bing-wallpapers' as a
key name, returning 404 'Setting not found' instead of hitting the actual
bing_wallpapers handler.
Fixed by adding a guard in get_setting() to skip these fixed path names,
and crucially by ensuring bing-wallpaper(s) routes are registered BEFORE
the /{key} catch-all in the router.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-05-31 20:59:26 +08:00
Your Name
e9af02dd22
fix: add bing-wallpapers (plural) to PUBLIC_PREFIXES for JWT bypass
2026-05-31 20:53:49 +08:00
Your Name
c9baecfdfa
feat: Bing wallpaper slideshow — 12 images, hourly rotation, weekly cleanup
...
- Frontend: fullscreen wallpaper background with 1.5s crossfade transition,
login card centered with glass effect, images rotate every hour
- Backend: new /api/settings/bing-wallpapers endpoint fetches 8 recent images
from Bing HPImageArchive, caches to web/app/wallpapers/, returns all URLs
- Auto-cleanup: removes files older than 7 days, keeps max 12 newest
- Old /bing-wallpaper endpoint kept for backward compatibility
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-05-31 20:51:50 +08:00
Your Name
3d5870b404
fix: correct wallpaper dir to 3 levels up (server/api/settings.py -> Nexus/web/app/wallpapers)
...
Path breakdown: __file__ is server/api/settings.py
.parent → server/api/
.parent.parent → server/
.parent.parent.parent → Nexus/ (repo root)
Then append web/app/wallpapers
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-05-31 20:38:35 +08:00
Your Name
afd32118b2
fix: correct wallpaper directory path in settings.py
...
- Path(__file__) is server/api/settings.py, so:
.parent → api/ .parent → server/ .parent → Nexus/ (ROOT)
.parent → (above ROOT — wrong!)
- Changed from .parent.parent.parent to .parent.parent.parent.parent
to reach the project root, then into web/app/wallpapers/
- Moved _WALLPAPER_DIR.mkdir into the async function body
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-05-31 20:34:27 +08:00
Your Name
d0308aaef6
fix: allow /app/wallpapers/ through AppAuthMiddleware
...
- Added /app/wallpapers/ to _APP_PUBLIC_PREFIXES so cached wallpaper images
are served without requiring login auth
- Wallpaper files are now saved to web/app/wallpapers/ by bing_wallpaper() endpoint
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-05-31 20:30:46 +08:00
Your Name
04dda2c419
fix: download Bing wallpaper to server disk, auto-clean weekly
...
- Changed bing-wallpaper endpoint from URL proxy to image downloader
- Saves wallpaper to web/app/wallpapers/YYYY-MM-DD.jpg
- Auto-deletes wallpapers older than 7 days on each request
- Falls back to yesterday's cached file if download fails
- Added Path import for filesystem access
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-05-31 20:23:55 +08:00
Your Name
e084d90c61
fix: add Bing wallpaper proxy endpoint, make it public (no JWT required)
...
- Added GET /api/settings/bing-wallpaper — proxies cn.bing.com HPImageArchive
to avoid CORS issues, returns {url} for the daily wallpaper
- Added /api/settings/bing-wallpaper to PUBLIC_PREFIXES in auth_jwt.py
so the login page can fetch it without authentication
- Login page now fetches wallpaper via backend proxy instead of direct CORS-blocked fetch
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-05-31 20:12:09 +08:00
Your Name
24aa8494e5
security: bind uvicorn to 127.0.0.1 instead of 0.0.0.0
...
The install wizard wrote '--host 0.0.0.0' which exposed the raw uvicorn
port 8600 on the public IP, bypassing Nginx HTTPS/TLS/WAF/middleware.
Changed to 127.0.0.1 — only local Nginx can reach the backend.
Also applied to running server via supervisor config fix.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-05-31 17:04:28 +08:00
Your Name
5c7775c10c
chore: remove old Tailwind HTML pages from git
...
Vuetify SPA is now the sole frontend entry point at /app/.
Old pages (alerts/servers/scripts/...html) replaced by Vue router.
Keep install.html for setup wizard.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-05-31 15:46:29 +08:00
Your Name
7a6479dbfa
fix: remove stale login.html from public paths, clean up prefixes
...
Old Tailwind HTML pages removed from server — Vuetify SPA is now
the sole entry at /app/. Only install.html remains for setup wizard.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-05-31 15:44:56 +08:00
Your Name
0fdae981cf
fix: add ttf/eot/otf to static asset whitelist in AppAuthMiddleware
...
Vuetify/Monaco fonts return 404 without these extensions whitelisted.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-05-31 15:42:43 +08:00
Your Name
3419ab8a09
chore: remove obsolete design department agent docs
...
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-05-31 15:37:57 +08:00
Your Name
d512460dc9
fix: frontend type definitions match actual backend API responses
...
- AlertsPage: template fields alert_type/value/is_recovery (was type/message/recovered)
- CommandsPage: remove non-existent is_dangerous/duration/admin_name; use admin_username
- ScriptsPage: ExecHistoryItem matches /scripts/executions response shape
- types/api.ts: CommandLogItem + SshSessionItem + ScriptExecItem aligned to backend
- Remove unused PaginatedResponse imports from CommandsPage/ScriptsPage
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-05-31 15:37:41 +08:00
Your Name
0f02e047cc
docs: update deployment instructions for Vuetify SPA
...
Nexus CI/CD / test (push) Waiting to run
Nexus CI/CD / deploy (push) Blocked by required conditions
Nexus Pre-commit Checks / quick-check (push) Waiting to run
- Split backend/frontend deploy steps
- Add deploy-frontend.sh one-liner reference
- Document AppAuthMiddleware 404 and stale HTML troubleshooting
- Remove obsolete dist copy instructions
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-05-31 13:25:33 +08:00
Your Name
35583115ff
fix: Vite outputs directly to web/app/ — no dist copy needed
...
- vite.config.mts: outDir changed from web/app/dist to web/app
- .gitignore: ignore web/app/index.html + web/app/assets/ (build artifacts)
- deploy/deploy-frontend.sh: automated build+deploy+verify script
Deployment is now: bash deploy/deploy-frontend.sh
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-05-31 13:24:22 +08:00
Your Name
f745714530
fix: allow Vuetify SPA index.html through AppAuthMiddleware
...
The new Vuetify SPA uses hash routing — all pages served from single
index.html. The old middleware only whitelisted individual HTML page
paths (login.html etc.), blocking the SPA entry point with 404.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-05-31 13:13:13 +08:00
Your Name
0d056a45e9
feat: Vuetify 4 frontend — complete rebuild with audit fix
...
Vue 3 + Vuetify 4 + TypeScript + Vue Router 4 + Pinia frontend,
replacing the old Tailwind+Alpine.js static pages.
Infrastructure (8 new files):
- composables/useSnackbar.ts — centralized notifications
- composables/useServerList.ts — server dropdown data
- composables/useServerPagination.ts — paginated server table
- types/api.ts — 14 typed API response interfaces
- types/global.d.ts — Window augmentation
- utils/status.ts — server status display helpers
- utils/validation.ts — 8 form validation rules
- components/MonacoEditor.vue — fullscreen code editor
14 pages rebuilt:
- LoginPage, DashboardPage, ServersPage, TerminalPage
- FilesPage, PushPage, ScriptsPage, CredentialsPage
- SchedulesPage, RetriesPage, CommandsPage
- AlertsPage, AuditPage, SettingsPage
Critical fixes (from audit):
- Files upload JWT auth (was missing Authorization header)
- API Key reveal password verification dialog
- 6 silent catch blocks → snackbar error feedback
- 33 as any → 0 (typed interfaces + global.d.ts)
- Dashboard: alerts/summary/categories/audit data loading
- WebSocket reconnect timer cleanup + auth failure handling
- Terminal ResizeObserver leak fix
- PushPage timer cleanup on unmount
- FilesPage path double-slash fix (joinPath helper)
- Filter changes reset pagination to page 1
Features added:
- Servers: batch operations, CSV export/import, detail panel
- Push: sync modes, ZIP upload, WebSocket real-time progress, cancel
- Scripts: quick execute panel, execution status tracking
- Files: Monaco editor, context menu, batch delete, rename, chmod
- Terminal: right-click menu, server sidebar, tab persistence
- Settings: batch save, TOTP manual key, password TOTP verification
- Dashboard: category distribution, recent audit, WS refresh
Quality:
- vue-tsc --noEmit zero errors
- vite build passes (1613 modules)
- Formal 8-step security audit passed (0 FINDING)
- .gitignore: dist/ → **/dist/ to cover web/app/dist/
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-05-31 12:56:12 +08:00
Your Name
0ded4a28ec
fix: 主题系统改用CSS变量 — dark:前缀在浏览器CDN不生效
...
根因: Tailwind v4 浏览器CDN(tailwindcss-browser.js)不处理外部CSS的
@custom-variant指令, dark:前缀规则完全不生成
方案: 改用CSS变量 + :root.dark {} 选择器
- theme.css: :root 定义亮色值, :root.dark 定义暗色值
- 15个HTML页面: 恢复 bg-[var(--bg-page)] 等CSS变量class
- 移除所有 dark: 前缀class(CSS变量自动适配)
- theme-init.js: 同步读localStorage设.dark class(FOUC防护)
- layout.js: toggleTheme 切换 .dark class + localStorage + MySQL
优势: CSS变量方案不依赖Tailwind dark:变体, 100%兼容浏览器CDN
2026-05-31 04:18:55 +08:00
Your Name
5ac4a5c7cf
fix: theme.css 加 @import tailwindcss 使 dark: 变体生效
...
Tailwind v4 官方文档确认:
@import 'tailwindcss';
@custom-variant dark (&:where(.dark, .dark *));
浏览器CDN build需要 @import 来处理 @custom-variant 指令
2026-05-31 04:13:26 +08:00
Your Name
9c5ebdfdbd
feat: 全站主题完全重做 — CSS变量→Tailwind dark: 前缀
...
设计依据: HyperUI/Flowbite/daisyUI/Meraki UI 深度调研
配色方案: HyperUI 全局色值映射 (gray-* 色系)
改动:
- theme.css: 重写为 @custom-variant dark 配置
- theme-init.js: FOUC防护 — 同步读localStorage设.dark class
- layout.js: 主题系统改用 .dark class + localStorage
- 15个HTML页面: 649处CSS变量class替换为dark:前缀
bg-[var(--bg-page)] → bg-gray-50 dark:bg-gray-950
bg-[var(--bg-card)] → bg-white dark:bg-gray-900
bg-[var(--bg-surface)] → bg-gray-100 dark:bg-gray-800
border-[var(--border)] → border-gray-200 dark:border-gray-700
text-[var(--text-primary)] → text-gray-900 dark:text-white
等9种映射
- design spec: docs/design/specs/2026-05-31-ui-redesign-design.md
修复: FOUC(切换主题时闪暗色)已解决
2026-05-31 04:11:17 +08:00
Your Name
c457cb4058
feat: dark mode theme system with synchronous FOUC prevention
...
- Add vendor/theme-init.js for synchronous dark mode init in <head>
- Update all 13 frontend pages with dark: variant classes
- Dark mode as default, light mode via localStorage toggle
- Remove redundant theme.css rules in favor of Tailwind dark: classes
- Add settings-dark-theme.png reference screenshot
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-05-31 03:54:30 +08:00
Your Name
8b2263916c
feat: design department agents integrate Tailwind ecosystem knowledge (9 sites)
...
Deep-learned 9 Tailwind CSS ecosystem sites and injected into all design
department agents via knowledge graph references:
- HyperUI (350+ components, Tailwind v4, Alpine.js) ⭐ best match
- Meraki UI (198 components, Application UI, RTL)
- Flowbite (56+ components, data-attr driven, Figma)
- daisyUI (65 semantic components, 35 themes)
- UIBak (200+ components, Alpine.js native)
- Headless UI (a11y benchmark, data-* patterns)
- Tailblocks (63 landing page blocks)
- Kutty (plugin architecture reference, unmaintained)
- WindyToolbox (resource directory)
Updated 10 files: design-department, ui-designer, ux-architect,
frontend-designer, color-curator, inspiration-analyzer, trend-researcher,
moodboard-creator, design-wizard, team roles.
Knowledge graph IDs for cross-session reference:
tailwind-css-9 (overview)
tailwind-css-9/hyperui-nexus-tailwind
tailwind-css-9/meraki-ui-rtl-tailwind
tailwind-css-9/flowbite-tailwind-bootstrap
tailwind-css-9/daisyui-tailwind
tailwind-css-9/uibak-alpinejs
tailwind-css-9/headless-ui-tailwind-labs
tailwind-css-9/tailblocks-landing-page
tailwind-css-9/kutty-tailwind-plugin-alpinejs
tailwind-css-9/windytoolbox-tailwind
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-05-31 03:53:40 +08:00
Your Name
293a0d64fe
feat: 全站亮色/暗色主题切换
...
实现方案: CSS自定义属性 + Tailwind arbitrary values
新增文件:
- web/app/vendor/theme.css — CSS变量定义(亮色+暗色)
修改文件 (15个HTML + 2个JS + 2个Python):
- layout.js — 侧边栏🌙 主题切换按钮 + loadTheme/toggleTheme
- settings.py — MUTABLE_KEYS加theme/editor_theme
- 15个HTML页面 — bg-slate-*替换为bg-[var(--bg-*)] + 引入theme.css
替换统计:
- index.html: 48处
- servers.html: 183处
- files.html: 94处
- push.html: 157处
- scripts.html: 83处
- credentials.html: 100处
- schedules.html: 59处
- retries.html: 40处
- commands.html: 57处
- alerts.html: 47处
- audit.html: 32处
- settings.html: 125处
- terminal.html: 89处
- install.html: 72处
- login.html: 14处
总计: 1199处替换
功能:
- 侧边栏底部🌙 /☀️ 按钮切换亮色/暗色
- 主题偏好保存到MySQL(settings表)
- 页面加载时自动恢复主题
- Monaco编辑器主题独立控制(⚙️ 菜单)
2026-05-31 02:55:45 +08:00
Your Name
94fbdf7b2d
refactor: 主题切换移到 ⚙️ 设置下拉菜单
...
Nexus CI/CD / test (push) Waiting to run
Nexus CI/CD / deploy (push) Blocked by required conditions
Nexus Pre-commit Checks / quick-check (push) Waiting to run
- 移除标题栏独立主题按钮(🌙 /☀️ )
- 新增⚙️ 设置按钮 → 下拉菜单
- 菜单项: 「☀️ 亮色主题」/「🌙 暗色主题」动态文字
- 点击菜单外自动关闭
- 菜单样式: bg-slate-800, rounded, shadow, 最小宽度200px
2026-05-31 02:42:24 +08:00
Your Name
e65c9993a2
feat: 编辑器亮色/暗色主题切换 + 保存到MySQL
...
- 标题栏🌙 /☀️ 按钮切换 Monaco 主题
- 'vs'(亮色) / 'vs-dark'(暗色)
- 切换后立即应用到所有打开的标签页
- 通过 PUT /api/settings/editor_theme 保存到MySQL
- 页面加载时自动读取保存的主题偏好
- settings.py MUTABLE_KEYS 白名单加 editor_theme
2026-05-31 02:39:21 +08:00