# 前端架构规范 > 本文档定义钢琴练习方案系统的模板架构设计,作为前端开发的遵循规范。 ## 1. 模板架构 ### 1.1 继承模式 所有业务页面必须继承自 `base.html`: ``` base.html (基础模板) ├── index.html (学员管理) ├── home.html (默认首页) ├── student.html (学员详情) ├── plan_edit.html (方案编辑) ├── settings.html (问题配置) ├── classes.html (班级管理) ├── users.html (用户管理) ├── templates.html (模板管理) └── api_settings.html (API设置) ``` ### 1.2 base.html 结构 `base.html` 统一管理以下公共部分: | 部分 | 说明 | |------|------| | CDN 引入 | Bootstrap 5.3, Bootstrap Icons, EasyMDE, Tabulator | | 基础 CSS | body, sidebar, main-content, card 样式 | | 移动端响应式 | 汉堡菜单、侧边栏展开/收起 | | 顶部导航栏 | 移动端显示(固定在顶部) | | 侧边栏结构 | 桌面端显示 | | 公共 JS | toggleMobileNav, logout, showChangePasswordModal | | 修改密码弹窗 | 统一放在 base 中 | ### 1.3 Jinja2 Blocks | Block 名称 | 位置 | 用途 | |------------|------|------| | `title` | `` | 页面标题 | | `extra_css` | `<head>` 末尾 | 额外 CSS(如 CDN 样式链接) | | `page_css` | `<style>` 末尾 | 页面特定 CSS | | `sidebar_nav` | 侧边栏 `<nav>` 内 | 导航链接 | | `content` | 主内容区 | 页面主要内容 HTML | | `extra_js` | `</body>` 前 | 额外 JS(如 CDN 脚本、页面业务逻辑) | ## 2. 新页面创建规范 ### 2.1 最小模板示例 ```html {% extends "base.html" %} {% block title %}页面标题 - 钢琴练习方案系统{% endblock %} {% block page_css %} <style> /* 仅放置页面特有的 CSS */ </style> {% endblock %} {% block sidebar_nav %} <!-- 复制 base.html 的导航结构,根据当前页面的 active 状态调整 --> <a class="nav-link" href="/"> <i class="bi bi-people"></i> 学员管理 </a> <!-- ... 其他链接 ... --> {% endblock %} {% block content %} <!-- 页面主要内容 HTML --> {% endblock %} {% block extra_js %} <script src="https://cdn.jsdelivr.net/npm/xxx/xxx.min.js"></script> <script> // 页面业务逻辑 JS </script> {% endblock %} ``` ### 2.2 侧边栏导航 active 状态 当前页面对应的链接需要添加 `active` class: ```html <a class="nav-link active" href="/settings"> <i class="bi bi-gear"></i> 问题配置 </a> ``` ### 2.3 用户信息显示 base.html 在移动端和桌面端都有用户信息占位符,页面 JS 需要在 DOMContentLoaded 中设置: ```javascript document.addEventListener('DOMContentLoaded', function() { fetch('/api/check-login').then(r => r.json()).then(data => { const userDisplay = data.username + ' (' + (data.role === 'admin' ? '管理员' : '普通用户') + ')'; document.getElementById('currentUserDisplay').textContent = userDisplay; const mobileDisplay = document.getElementById('mobileUserDisplay'); if (mobileDisplay) mobileDisplay.textContent = userDisplay; }); }); ``` ## 3. 移动端响应式设计 ### 3.1 断点 | 断点 | 屏幕宽度 | 布局 | |------|----------|------| | 桌面端 | ≥ 768px | 侧边栏固定在左侧,主内容区在右侧 | | 移动端 | < 768px | 顶部导航栏 + 隐藏侧边栏(汉堡按钮展开) | ### 3.2 CSS 规范 所有移动端样式统一写在 `base.html` 的 `@media (max-width: 767.98px)` 块中,各页面不需要重复定义。 侧边栏移动端样式(base.html): ```css /* 移动端响应式 */ @media (max-width: 767.98px) { .sidebar { position: fixed; top: 60px; /* 向下偏移,避免被顶部导航栏挡住 */ left: 0; width: 100%; min-height: auto; max-height: calc(100vh - 60px); /* 最大高度为屏幕高度减去导航栏 */ z-index: 1040; overflow-y: auto; transform: translateY(-100%); /* 默认隐藏 */ transition: transform 0.3s ease; } .sidebar.collapsed { transform: translateY(-100%); /* 隐藏状态 */ } .sidebar:not(.collapsed) { transform: translateY(0); /* 显示状态 */ } .main-content { margin-top: 60px; padding: 10px; } .mobile-nav-toggle { display: flex !important; } } ``` ### 3.3 移动端导航栏 HTML(base.html) ```html <nav class="mobile-nav-toggle navbar navbar-dark bg-dark d-flex d-md-none" style="position:fixed;top:0;left:0;right:0;z-index:1050;padding:10px;"> <div class="container-fluid d-flex justify-content-between align-items-center"> <div> <span class="navbar-brand mb-0"><i class="bi bi-music-note-beamed"></i> 钢琴方案</span> <small id="mobileUserDisplay" class="d-block text-white-50" style="font-size:10px;"></small> </div> <button class="btn btn-outline-light btn-sm" onclick="toggleMobileNav()"> <i class="bi bi-list"></i> </button> </div> </nav> ``` **注意**: - `mobile-nav-toggle` 类控制显示/隐藏(桌面端隐藏,移动端显示) - `z-index: 1050` 确保在侧边栏之上(侧边栏是 1040) ## 4. JavaScript 规范 ### 4.1 公共函数(base.html 提供) | 函数 | 用途 | |------|------| | `toggleMobileNav()` | 切换侧边栏展开/收起 | | `logout()` | 退出登录 | | `showChangePasswordModal()` | 显示修改密码弹窗 | ### 4.2 页面 JS 放置 - 公共函数(如 `showToast`)放在 `extra_js` block 中 - 页面初始化逻辑放在 `document.addEventListener('DOMContentLoaded', ...)` 中 - 业务函数在 `extra_js` block 中定义 ### 4.3 修改密码 base.html 已包含修改密码弹窗 HTML 和 JS。各页面不需要重复定义 `showChangePasswordModal()` 和相关 DOM 绑定。 ## 5. 避免重复代码 ### 5.1 禁止重复的内容 以下内容**禁止**在各页面模板中重复定义: - `<head>` 标签内容(meta, title, CDN 链接) - 基础 CSS(body, sidebar, card 等) - 移动端响应式 CSS - 移动端顶部导航栏 HTML - 侧边栏 HTML 结构 - Bootstrap JS CDN - `toggleMobileNav()`, `logout()`, `showChangePasswordModal()` 函数 - 修改密码弹窗 HTML 和 JS ### 5.2 正确做法 | 如果需要... | 应该... | |-------------|---------| | 页面特定 CSS | 在 `{% block page_css %}` 中添加 | | 额外 JS 库 | 在 `{% block extra_js %}` 开头引入 | | 页面业务逻辑 | 在 `{% block extra_js %}` 中定义 | | 导航 active 状态 | 在 `{% block sidebar_nav %}` 中设置 | ## 6. 文件结构 ``` app/templates/ ├── base.html # 基础模板(核心,统一侧边栏) ├── index.html # 学员管理 ├── home.html # 默认首页(统计信息) ├── student.html # 学员详情(URL导航) ├── plan_edit.html # 方案编辑(URL导航) ├── settings.html # 问题配置 ├── classes.html # 班级管理 ├── users.html # 用户管理 ├── templates.html # 模板管理 ├── api_settings.html # API设置 ├── login.html # 登录页(独立,无侧边栏) ├── setup.html # 初始化页(独立) └── wechat_card.html # 微信卡片(独立) ``` > 注意:`login.html`、`setup.html`、`wechat_card.html` 是独立页面,不继承 base.html。 ## 7. URL 导航模式 系统支持两种导航模式: | 模式 | 说明 | 示例 | |------|------|------| | SPA 模式 | 点击学员卡片弹窗查看详情 | 原 index.html 模式 | | URL 模式 | 通过 URL 直接访问 | `/student/<id>`, `/plan/<id>/edit` | 推荐使用 URL 模式,便于分享和书签。 ## 8. 更新日志 | 日期 | 版本 | 变更内容 | |------|------|----------| | 2026-04-21 | v1.0 | 初始文档,定义 base.html 模板继承模式 | | 2026-04-23 | v1.1 | 添加 URL 导航模式说明;新增 home.html, student.html, plan_edit.html |