e084d90c61
- 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>
5.1 KiB
5.1 KiB
Nexus Vue 3 + Nuxt UI 前端重设计方案
技术栈
- 框架: Vue 3.5+ (Composition API +
<script setup>) - 构建: Vite 6 (多页应用 MPA 模式)
- UI 库: Nuxt UI v4 (125+ 组件, MIT)
- CSS: Tailwind CSS v4
- 图标: Iconify (Nuxt UI 内置 200k+ 图标)
- 暗色模式: Nuxt UI 内置
@nuxtjs/color-mode - 语言: TypeScript
前端目录结构
frontend/
├── index.html # Vite 入口
├── package.json
├── vite.config.ts # MPA 多页配置
├── tsconfig.json
├── src/
│ ├── main.ts # Vue app 初始化 + Nuxt UI 注册
│ ├── App.vue # 根布局(侧边栏 + header + router-view)
│ ├── router.ts # Vue Router (hash 模式)
│ ├── stores/ # Pinia 状态管理
│ │ ├── auth.ts # JWT 令牌 + 用户信息
│ │ └── theme.ts # 暗色/亮色切换
│ ├── composables/ # 可复用逻辑
│ │ ├── useApi.ts # fetch 封装 (JWT + 自动刷新)
│ │ ├── useToast.ts # Toast 通知
│ │ └── useWebSocket.ts # WebSocket 连接
│ ├── components/ # 共享组件
│ │ ├── ui/ # Nuxt UI 包装
│ │ ├── layout/
│ │ │ ├── AppSidebar.vue
│ │ │ ├── AppHeader.vue
│ │ │ └── AppLayout.vue
│ │ └── common/
│ │ ├── ServerStatusBadge.vue
│ │ ├── ConfirmModal.vue
│ │ └── EmptyState.vue
│ ├── pages/ # 页面组件
│ │ ├── LoginPage.vue
│ │ ├── DashboardPage.vue
│ │ ├── ServersPage.vue
│ │ ├── ServerDetailPage.vue
│ │ ├── FilesPage.vue
│ │ ├── PushPage.vue
│ │ ├── ScriptsPage.vue
│ │ ├── ScriptExecutionsPage.vue
│ │ ├── CredentialsPage.vue
│ │ ├── SchedulesPage.vue
│ │ ├── RetriesPage.vue
│ │ ├── CommandsPage.vue
│ │ ├── AlertsPage.vue
│ │ ├── AuditPage.vue
│ │ ├── SettingsPage.vue
│ │ └── TerminalPage.vue
│ └── types/ # TypeScript 类型
│ ├── api.ts # API 响应类型
│ └── models.ts # 数据模型
└── public/
└── favicon.svg
页面路由
| 路径 | 页面 | 原 HTML |
|---|---|---|
/ |
DashboardPage | index.html |
/servers |
ServersPage | servers.html |
/servers/:id |
ServerDetailPage | servers.html detail panel |
/files |
FilesPage | files.html |
/push |
PushPage | push.html |
/scripts |
ScriptsPage | scripts.html |
/scripts/executions |
ScriptExecutionsPage | script-executions.html |
/credentials |
CredentialsPage | credentials.html |
/schedules |
SchedulesPage | schedules.html |
/retries |
RetriesPage | retries.html |
/commands |
CommandsPage | commands.html |
/alerts |
AlertsPage | alerts.html |
/audit |
AuditPage | audit.html |
/settings |
SettingsPage | settings.html |
/terminal/:serverId |
TerminalPage | terminal.html |
/login |
LoginPage | login.html |
Nuxt UI 组件映射
| 当前 HTML 模式 | Nuxt UI 组件 |
|---|---|
| 侧边栏 | UNavigationMenu |
| Header | UHeader |
| 表格 | UTable |
| 分页 | UPagination |
| 按钮 | UButton |
| 输入框 | UInput |
| Select | USelect / USelectMenu |
| Textarea | UTextarea |
| Modal | UModal |
| 卡片 | UCard |
| 标签页 | UTabs |
| Toast | Nuxt UI toast |
| 下拉菜单 | UDropdownMenu |
| 开关 | UToggle |
| 复选框 | UCheckbox |
| 面包屑 | UBreadcrumb |
| 头像 | UAvatar |
| 进度条 | UProgress |
| 骨架屏 | USkeleton |
| 空状态 | UEmptyState |
与原 HTML 版本的差异
- 组件化:一个
UButton替换 10 行内联 Tailwind - 类型安全:API 响应有 TypeScript 类型
- 开发体验:HMR 热更新,不用手动刷新
- 代码量:预估减少 60% (1200 行 servers.html → ~400 行 ServersPage.vue)
- 部署:
npm run build→dist/→ scp 到服务器 - 后端不变:所有 Python API 完全不动
实施计划
Phase 1: 项目脚手架
- vite + vue + nuxt-ui 初始化
- 路由 + 暗色模式 + API 封装
Phase 2: 逐页面迁移(按复杂度排序)
- LoginPage.vue(最简单)
- DashboardPage.vue
- ServersPage.vue + ServerDetailPage.vue(最复杂)
- SettingsPage.vue
- ScriptsPage.vue
- PushPage.vue
- FilesPage.vue
- SchedulesPage.vue
- CredentialsPage.vue
- RetriesPage.vue
- CommandsPage.vue
- AlertsPage.vue
- AuditPage.vue
- TerminalPage.vue
Phase 3: 部署
- build → dist/
- scp 到服务器
/www/wwwroot/api.synaglobal.vip/app/ - 后端静态文件路径指向 dist/
不改变的部分
- ✅ 所有 Python 后端 API
- ✅ API 端点路径
- ✅ JWT 认证流程
- ✅ 部署域名 https://api.synaglobal.vip