使用new_web中的内容开始重写会员部分原型
This commit is contained in:
		
							parent
							
								
									75f3418a7e
								
							
						
					
					
						commit
						e6065a5f8f
					
				|  | @ -0,0 +1,203 @@ | |||
| # 信息管理系统原型项目 | ||||
| 
 | ||||
| ## 项目概述 | ||||
| 这是一个传统的中文信息管理系统原型,采用纯HTML/CSS/JavaScript技术栈,实现左侧菜单栏 + 中央tab展示区域的经典布局。项目专注于演示系统架构和交互流程,不追求视觉美观。 | ||||
| 
 | ||||
| ## 核心架构 | ||||
| 
 | ||||
| ### 技术栈 | ||||
| - **前端**: 纯HTML5 + CSS3 + 原生JavaScript ES6+ | ||||
| - **架构模式**: 单页应用(SPA) + 动态内容加载 | ||||
| - **样式系统**: 自定义CSS,无外部框架依赖 | ||||
| - **模块化**: 页面内容与逻辑完全分离 | ||||
| 
 | ||||
| ### 文件结构 | ||||
| ``` | ||||
| merchant/ | ||||
| ├── index.html              # 主框架页面 | ||||
| ├── styles.css              # 全局样式文件 | ||||
| ├── script.js               # 核心JavaScript逻辑 | ||||
| ├── pages/                  # 页面内容目录 | ||||
| │   ├── level-settings.html    # 等级设置页面 | ||||
| │   └── member-view.html       # 会员查看页面 | ||||
| └── CLAUDE.md               # 项目文档 | ||||
| ``` | ||||
| 
 | ||||
| ### 架构特点 | ||||
| 1. **内容与逻辑分离**: 所有页面内容存储为独立HTML文件 | ||||
| 2. **动态加载**: 使用fetch API异步加载页面内容 | ||||
| 3. **Tab管理**: 支持多页面同时打开,可独立关闭 | ||||
| 4. **菜单系统**: 二级菜单展开/收起,防重复打开 | ||||
| 
 | ||||
| ## 核心功能 | ||||
| 
 | ||||
| ### 左侧菜单系统 | ||||
| - **一级菜单**: 主功能模块入口 | ||||
| - **二级菜单**: 具体功能页面,点击展开/收起 | ||||
| - **当前实现**: 会员管理 > 等级设置、会员查看 | ||||
| 
 | ||||
| ### 中央Tab系统 | ||||
| - **多页面管理**: 支持同时打开多个页面tab | ||||
| - **防重复**: 相同页面不会重复打开,直接激活已存在tab | ||||
| - **可关闭**: 每个tab都有独立关闭按钮(首页除外) | ||||
| - **智能切换**: 关闭当前tab时自动激活相邻tab | ||||
| 
 | ||||
| ### 页面加载机制 | ||||
| - **异步加载**: 使用`fetch`API动态加载HTML内容 | ||||
| - **错误处理**: 包含完整的加载失败降级方案 | ||||
| - **缓存管理**: 每次点击都重新加载,保证内容最新 | ||||
| 
 | ||||
| ## 开发约束和规范 | ||||
| 
 | ||||
| ### 重要约束 ⚠️ | ||||
| 1. **禁止硬编码HTML**: 所有页面内容必须存储在独立的HTML文件中 | ||||
| 2. **优先编辑现有文件**: 禁止随意创建新文件,优先修改现有文件 | ||||
| 3. **保持架构一致性**: 新页面必须遵循现有的加载和展示模式 | ||||
| 4. **中文本地化**: 所有界面文本必须使用中文 | ||||
| 
 | ||||
| ### 开发规范 | ||||
| ```javascript | ||||
| // 添加新页面的步骤: | ||||
| // 1. 在pages/目录创建对应的HTML文件 | ||||
| // 2. 在HTML中添加新的菜单项,指向该页面 | ||||
| // 3. 确保contentType参数与文件名匹配 | ||||
| 
 | ||||
| // 正确的调用方式: | ||||
| onclick="openTab('新页面', 'new-page')" | ||||
| // 对应文件:pages/new-page.html | ||||
| ``` | ||||
| 
 | ||||
| ### 文件命名规范 | ||||
| - 页面文件:`pages/功能名称.html` (使用kebab-case) | ||||
| - contentType参数:与文件名保持一致 | ||||
| - Tab标题:使用中文友好名称 | ||||
| 
 | ||||
| ## 核心函数说明 | ||||
| 
 | ||||
| ### `openTab(title, contentType)` | ||||
| - **参数**: title(中文标题), contentType(文件名前缀) | ||||
| - **功能**: 创建新tab并异步加载页面内容 | ||||
| - **特性**: 防重复打开、错误处理、自动激活 | ||||
| 
 | ||||
| ### `loadPageContent(contentType)` | ||||
| - **参数**: contentType(对应pages/目录下的文件名) | ||||
| - **返回**: Promise<string> HTML内容 | ||||
| - **错误处理**: 加载失败时返回默认提示内容 | ||||
| 
 | ||||
| ### `toggleSubmenu(submenuId)` | ||||
| - **参数**: submenuId(子菜单DOM元素ID) | ||||
| - **功能**: 切换子菜单展开/收起状态 | ||||
| - **特性**: 互斥展开(同时只能展开一个子菜单) | ||||
| 
 | ||||
| ## 扩展指南 | ||||
| 
 | ||||
| ### 添加新的功能模块 | ||||
| 1. **创建一级菜单**: | ||||
|    ```html | ||||
|    <div class="menu-item"> | ||||
|        <div class="menu-title" onclick="toggleSubmenu('new-submenu')"> | ||||
|            <span>新功能模块</span> | ||||
|            <span class="arrow">▼</span> | ||||
|        </div> | ||||
|        <div class="submenu" id="new-submenu"> | ||||
|            <!-- 二级菜单项 --> | ||||
|        </div> | ||||
|    </div> | ||||
|    ``` | ||||
| 
 | ||||
| 2. **添加二级菜单项**: | ||||
|    ```html | ||||
|    <div class="submenu-item" onclick="openTab('功能名称', 'function-name')"> | ||||
|        功能名称 | ||||
|    </div> | ||||
|    ``` | ||||
| 
 | ||||
| 3. **创建页面内容**: | ||||
|    ```bash | ||||
|    # 在pages/目录创建对应HTML文件 | ||||
|    pages/function-name.html | ||||
|    ``` | ||||
| 
 | ||||
| ### 页面内容模板 | ||||
| ```html | ||||
| <div class="page-content"> | ||||
|     <h2>页面标题</h2> | ||||
|      | ||||
|     <!-- 表单区域 --> | ||||
|     <div class="form-group"> | ||||
|         <label>字段名称:</label> | ||||
|         <input type="text" placeholder="请输入..."> | ||||
|     </div> | ||||
|      | ||||
|     <!-- 操作按钮 --> | ||||
|     <button class="btn btn-primary">主要操作</button> | ||||
|     <button class="btn">次要操作</button> | ||||
|      | ||||
|     <!-- 数据表格 --> | ||||
|     <table class="table"> | ||||
|         <thead> | ||||
|             <tr> | ||||
|                 <th>列标题</th> | ||||
|             </tr> | ||||
|         </thead> | ||||
|         <tbody> | ||||
|             <tr> | ||||
|                 <td>数据内容</td> | ||||
|             </tr> | ||||
|         </tbody> | ||||
|     </table> | ||||
| </div> | ||||
| ``` | ||||
| 
 | ||||
| ## 样式系统 | ||||
| 
 | ||||
| ### CSS类命名规范 | ||||
| - `.page-content`: 页面内容容器 | ||||
| - `.form-group`: 表单字段组 | ||||
| - `.btn`, `.btn-primary`: 按钮样式 | ||||
| - `.table`: 数据表格 | ||||
| - `.menu-item`, `.submenu-item`: 菜单项 | ||||
| 
 | ||||
| ### 主题色彩 | ||||
| - 主色调:深蓝色 `#2c3e50` | ||||
| - 高亮色:蓝色 `#3498db` | ||||
| - 背景色:浅灰 `#f5f5f5` | ||||
| - 边框色:灰色 `#bdc3c7` | ||||
| 
 | ||||
| ## 测试和部署 | ||||
| 
 | ||||
| ### 本地运行 | ||||
| ```bash | ||||
| # 推荐使用本地HTTP服务器(必需,因为使用了fetch API) | ||||
| python -m http.server 8000 | ||||
| # 或 | ||||
| npx serve . | ||||
| # 然后访问 http://localhost:8000 | ||||
| ``` | ||||
| 
 | ||||
| ### 浏览器兼容性 | ||||
| - Chrome 60+ (支持fetch API和ES6 async/await) | ||||
| - Firefox 55+ | ||||
| - Safari 12+ | ||||
| - Edge 79+ | ||||
| 
 | ||||
| ### 快捷键 | ||||
| - `ESC`: 关闭当前激活的tab(首页除外) | ||||
| 
 | ||||
| ## 注意事项 | ||||
| 
 | ||||
| ### 开发限制 | ||||
| - ❌ 不要在JavaScript中硬编码HTML内容 | ||||
| - ❌ 不要随意创建新文件,优先编辑现有文件 | ||||
| - ❌ 不要破坏现有的架构模式 | ||||
| - ✅ 所有页面内容必须存储在pages/目录 | ||||
| - ✅ 使用中文界面文本 | ||||
| - ✅ 遵循现有的命名和结构约定 | ||||
| 
 | ||||
| ### 技术限制 | ||||
| - 必须运行在HTTP服务器环境(不支持file://协议) | ||||
| - 依赖现代浏览器的fetch API和ES6特性 | ||||
| - 所有数据都是前端模拟,无后端API集成 | ||||
| 
 | ||||
| ## 项目目标 | ||||
| 此项目是一个快速原型系统,用于演示传统管理系统的布局意图和交互流程。专注于功能架构而非视觉设计,为后续开发提供清晰的技术基础和扩展方向。 | ||||
|  | @ -0,0 +1,51 @@ | |||
| <!DOCTYPE html> | ||||
| <html lang="zh-CN"> | ||||
| <head> | ||||
|     <meta charset="UTF-8"> | ||||
|     <meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||||
|     <title>信息管理系统</title> | ||||
|     <link rel="stylesheet" href="styles.css"> | ||||
| </head> | ||||
| <body> | ||||
|     <div class="container"> | ||||
|         <!-- 左侧菜单栏 --> | ||||
|         <div class="sidebar"> | ||||
|             <div class="logo"> | ||||
|                 <h2>管理系统</h2> | ||||
|             </div> | ||||
|             <nav class="menu"> | ||||
|                 <div class="menu-item"> | ||||
|                     <div class="menu-title" onclick="toggleSubmenu('member-submenu')"> | ||||
|                         <span>会员管理</span> | ||||
|                         <span class="arrow">▼</span> | ||||
|                     </div> | ||||
|                     <div class="submenu" id="member-submenu"> | ||||
|                         <div class="submenu-item" onclick="openTab('等级设置', 'level-settings')">等级设置</div> | ||||
|                         <div class="submenu-item" onclick="openTab('会员查看', 'member-view')">会员查看</div> | ||||
|                     </div> | ||||
|                 </div> | ||||
|             </nav> | ||||
|         </div> | ||||
| 
 | ||||
|         <!-- 中央内容区域 --> | ||||
|         <div class="main-content"> | ||||
|             <!-- Tab栏 --> | ||||
|             <div class="tab-bar"> | ||||
|                 <div class="tab active" id="home-tab"> | ||||
|                     <span>首页</span> | ||||
|                 </div> | ||||
|             </div> | ||||
| 
 | ||||
|             <!-- 内容展示区域 --> | ||||
|             <div class="content-area"> | ||||
|                 <div class="tab-content active" id="home-content"> | ||||
|                     <h1>欢迎使用信息管理系统</h1> | ||||
|                     <p>请从左侧菜单选择功能模块</p> | ||||
|                 </div> | ||||
|             </div> | ||||
|         </div> | ||||
|     </div> | ||||
| 
 | ||||
|     <script src="script.js"></script> | ||||
| </body> | ||||
| </html> | ||||
|  | @ -0,0 +1,57 @@ | |||
| <div class="page-content"> | ||||
|     <h2>等级设置</h2> | ||||
|     <div class="form-group"> | ||||
|         <label>等级名称:</label> | ||||
|         <input type="text" placeholder="请输入等级名称"> | ||||
|     </div> | ||||
|     <div class="form-group"> | ||||
|         <label>等级要求:</label> | ||||
|         <input type="number" placeholder="积分要求"> | ||||
|     </div> | ||||
|     <div class="form-group"> | ||||
|         <label>等级描述:</label> | ||||
|         <textarea placeholder="请输入等级描述" rows="3"></textarea> | ||||
|     </div> | ||||
|     <button class="btn btn-primary">保存设置</button> | ||||
|     <button class="btn">取消</button> | ||||
|      | ||||
|     <table class="table"> | ||||
|         <thead> | ||||
|             <tr> | ||||
|                 <th>等级名称</th> | ||||
|                 <th>积分要求</th> | ||||
|                 <th>会员数量</th> | ||||
|                 <th>操作</th> | ||||
|             </tr> | ||||
|         </thead> | ||||
|         <tbody> | ||||
|             <tr> | ||||
|                 <td>普通会员</td> | ||||
|                 <td>0</td> | ||||
|                 <td>1,234</td> | ||||
|                 <td> | ||||
|                     <button class="btn">编辑</button> | ||||
|                     <button class="btn">删除</button> | ||||
|                 </td> | ||||
|             </tr> | ||||
|             <tr> | ||||
|                 <td>银牌会员</td> | ||||
|                 <td>1,000</td> | ||||
|                 <td>567</td> | ||||
|                 <td> | ||||
|                     <button class="btn">编辑</button> | ||||
|                     <button class="btn">删除</button> | ||||
|                 </td> | ||||
|             </tr> | ||||
|             <tr> | ||||
|                 <td>金牌会员</td> | ||||
|                 <td>5,000</td> | ||||
|                 <td>123</td> | ||||
|                 <td> | ||||
|                     <button class="btn">编辑</button> | ||||
|                     <button class="btn">删除</button> | ||||
|                 </td> | ||||
|             </tr> | ||||
|         </tbody> | ||||
|     </table> | ||||
| </div> | ||||
|  | @ -0,0 +1,70 @@ | |||
| <div class="page-content"> | ||||
|     <h2>会员查看</h2> | ||||
|     <div class="form-group"> | ||||
|         <label>搜索会员:</label> | ||||
|         <input type="text" placeholder="请输入会员姓名或手机号"> | ||||
|     </div> | ||||
|     <div class="form-group"> | ||||
|         <label>会员等级:</label> | ||||
|         <select> | ||||
|             <option value="">全部等级</option> | ||||
|             <option value="normal">普通会员</option> | ||||
|             <option value="silver">银牌会员</option> | ||||
|             <option value="gold">金牌会员</option> | ||||
|         </select> | ||||
|     </div> | ||||
|     <button class="btn btn-primary">搜索</button> | ||||
|     <button class="btn">重置</button> | ||||
|      | ||||
|     <table class="table"> | ||||
|         <thead> | ||||
|             <tr> | ||||
|                 <th>会员ID</th> | ||||
|                 <th>姓名</th> | ||||
|                 <th>手机号</th> | ||||
|                 <th>等级</th> | ||||
|                 <th>积分</th> | ||||
|                 <th>注册时间</th> | ||||
|                 <th>操作</th> | ||||
|             </tr> | ||||
|         </thead> | ||||
|         <tbody> | ||||
|             <tr> | ||||
|                 <td>M001</td> | ||||
|                 <td>张小明</td> | ||||
|                 <td>138****1234</td> | ||||
|                 <td>金牌会员</td> | ||||
|                 <td>8,500</td> | ||||
|                 <td>2024-01-15</td> | ||||
|                 <td> | ||||
|                     <button class="btn">查看详情</button> | ||||
|                     <button class="btn">编辑</button> | ||||
|                 </td> | ||||
|             </tr> | ||||
|             <tr> | ||||
|                 <td>M002</td> | ||||
|                 <td>李小红</td> | ||||
|                 <td>139****5678</td> | ||||
|                 <td>银牌会员</td> | ||||
|                 <td>2,300</td> | ||||
|                 <td>2024-02-20</td> | ||||
|                 <td> | ||||
|                     <button class="btn">查看详情</button> | ||||
|                     <button class="btn">编辑</button> | ||||
|                 </td> | ||||
|             </tr> | ||||
|             <tr> | ||||
|                 <td>M003</td> | ||||
|                 <td>王小刚</td> | ||||
|                 <td>137****9012</td> | ||||
|                 <td>普通会员</td> | ||||
|                 <td>450</td> | ||||
|                 <td>2024-03-10</td> | ||||
|                 <td> | ||||
|                     <button class="btn">查看详情</button> | ||||
|                     <button class="btn">编辑</button> | ||||
|                 </td> | ||||
|             </tr> | ||||
|         </tbody> | ||||
|     </table> | ||||
| </div> | ||||
|  | @ -0,0 +1,190 @@ | |||
| // 全局变量
 | ||||
| let tabCounter = 0; | ||||
| let activeTabId = 'home-tab'; | ||||
| 
 | ||||
| // 页面加载完成后初始化
 | ||||
| document.addEventListener('DOMContentLoaded', function() { | ||||
|     initializeSystem(); | ||||
| }); | ||||
| 
 | ||||
| // 初始化系统
 | ||||
| function initializeSystem() { | ||||
|     console.log('信息管理系统已加载'); | ||||
| } | ||||
| 
 | ||||
| // 切换子菜单显示/隐藏
 | ||||
| function toggleSubmenu(submenuId) { | ||||
|     const submenu = document.getElementById(submenuId); | ||||
|     const arrow = submenu.parentElement.querySelector('.arrow'); | ||||
|      | ||||
|     if (submenu.classList.contains('expanded')) { | ||||
|         submenu.classList.remove('expanded'); | ||||
|         arrow.classList.remove('rotated'); | ||||
|     } else { | ||||
|         // 先关闭其他所有子菜单
 | ||||
|         const allSubmenus = document.querySelectorAll('.submenu'); | ||||
|         const allArrows = document.querySelectorAll('.arrow'); | ||||
|          | ||||
|         allSubmenus.forEach(menu => menu.classList.remove('expanded')); | ||||
|         allArrows.forEach(arrow => arrow.classList.remove('rotated')); | ||||
|          | ||||
|         // 展开当前子菜单
 | ||||
|         submenu.classList.add('expanded'); | ||||
|         arrow.classList.add('rotated'); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| // 打开新的tab页面
 | ||||
| async function openTab(title, contentType) { | ||||
|     tabCounter++; | ||||
|     const tabId = `tab-${tabCounter}`; | ||||
|     const contentId = `content-${tabCounter}`; | ||||
|      | ||||
|     // 检查是否已经存在相同标题的tab
 | ||||
|     const existingTab = Array.from(document.querySelectorAll('.tab')).find(tab =>  | ||||
|         tab.querySelector('span').textContent === title | ||||
|     ); | ||||
|      | ||||
|     if (existingTab) { | ||||
|         // 如果已存在,直接激活该tab
 | ||||
|         switchTab(existingTab.id); | ||||
|         return; | ||||
|     } | ||||
|      | ||||
|     // 创建新的tab
 | ||||
|     const tabBar = document.querySelector('.tab-bar'); | ||||
|     const newTab = document.createElement('div'); | ||||
|     newTab.className = 'tab'; | ||||
|     newTab.id = tabId; | ||||
|     newTab.innerHTML = ` | ||||
|         <span>${title}</span> | ||||
|         <button class="close-btn" onclick="closeTab('${tabId}')" aria-label="关闭">×</button> | ||||
|     `;
 | ||||
|      | ||||
|     // 添加点击事件
 | ||||
|     newTab.addEventListener('click', function(e) { | ||||
|         if (!e.target.classList.contains('close-btn')) { | ||||
|             switchTab(tabId); | ||||
|         } | ||||
|     }); | ||||
|      | ||||
|     tabBar.appendChild(newTab); | ||||
|      | ||||
|     // 创建对应的内容区域
 | ||||
|     const contentArea = document.querySelector('.content-area'); | ||||
|     const newContent = document.createElement('div'); | ||||
|     newContent.className = 'tab-content'; | ||||
|     newContent.id = contentId; | ||||
|      | ||||
|     // 动态加载页面内容
 | ||||
|     try { | ||||
|         const pageContent = await loadPageContent(contentType); | ||||
|         newContent.innerHTML = pageContent; | ||||
|     } catch (error) { | ||||
|         console.error('加载页面内容失败:', error); | ||||
|         newContent.innerHTML = ` | ||||
|             <div class="page-content"> | ||||
|                 <h2>${title}</h2> | ||||
|                 <p>页面加载失败,请稍后重试。</p> | ||||
|             </div> | ||||
|         `;
 | ||||
|     } | ||||
|      | ||||
|     contentArea.appendChild(newContent); | ||||
|      | ||||
|     // 激活新创建的tab
 | ||||
|     switchTab(tabId); | ||||
| } | ||||
| 
 | ||||
| // 切换到指定的tab
 | ||||
| function switchTab(tabId) { | ||||
|     // 移除所有tab的active状态
 | ||||
|     document.querySelectorAll('.tab').forEach(tab => { | ||||
|         tab.classList.remove('active'); | ||||
|     }); | ||||
|      | ||||
|     // 隐藏所有内容
 | ||||
|     document.querySelectorAll('.tab-content').forEach(content => { | ||||
|         content.classList.remove('active'); | ||||
|     }); | ||||
|      | ||||
|     // 激活指定的tab
 | ||||
|     const targetTab = document.getElementById(tabId); | ||||
|     if (targetTab) { | ||||
|         targetTab.classList.add('active'); | ||||
|         activeTabId = tabId; | ||||
|          | ||||
|         // 显示对应的内容
 | ||||
|         const contentId = tabId.replace('tab', 'content'); | ||||
|         const targetContent = document.getElementById(contentId); | ||||
|         if (targetContent) { | ||||
|             targetContent.classList.add('active'); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| // 关闭tab
 | ||||
| function closeTab(tabId) { | ||||
|     const tab = document.getElementById(tabId); | ||||
|     const contentId = tabId.replace('tab', 'content'); | ||||
|     const content = document.getElementById(contentId); | ||||
|      | ||||
|     if (!tab) return; | ||||
|      | ||||
|     // 如果关闭的是当前激活的tab
 | ||||
|     if (tabId === activeTabId) { | ||||
|         // 找到前一个tab来激活
 | ||||
|         const allTabs = document.querySelectorAll('.tab'); | ||||
|         let targetTab = null; | ||||
|          | ||||
|         for (let i = 0; i < allTabs.length; i++) { | ||||
|             if (allTabs[i].id === tabId) { | ||||
|                 // 优先选择前一个tab,如果没有就选择后一个
 | ||||
|                 targetTab = allTabs[i - 1] || allTabs[i + 1]; | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|          | ||||
|         if (targetTab) { | ||||
|             switchTab(targetTab.id); | ||||
|         } else { | ||||
|             // 如果没有其他tab,激活首页
 | ||||
|             switchTab('home-tab'); | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     // 移除tab和对应的内容
 | ||||
|     tab.remove(); | ||||
|     if (content) { | ||||
|         content.remove(); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| // 动态加载页面内容
 | ||||
| async function loadPageContent(contentType) { | ||||
|     try { | ||||
|         const response = await fetch(`pages/${contentType}.html`); | ||||
|         if (!response.ok) { | ||||
|             throw new Error(`HTTP error! status: ${response.status}`); | ||||
|         } | ||||
|         const content = await response.text(); | ||||
|         return content; | ||||
|     } catch (error) { | ||||
|         console.error('加载页面失败:', error); | ||||
|         // 返回默认内容
 | ||||
|         return ` | ||||
|             <div class="page-content"> | ||||
|                 <h2>页面加载中...</h2> | ||||
|                 <p>页面正在开发中,敬请期待...</p> | ||||
|             </div> | ||||
|         `;
 | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| // 键盘快捷键支持
 | ||||
| document.addEventListener('keydown', function(e) { | ||||
|     // ESC键关闭当前tab(除了首页)
 | ||||
|     if (e.key === 'Escape' && activeTabId !== 'home-tab') { | ||||
|         closeTab(activeTabId); | ||||
|     } | ||||
| }); | ||||
|  | @ -0,0 +1,243 @@ | |||
| * { | ||||
|     margin: 0; | ||||
|     padding: 0; | ||||
|     box-sizing: border-box; | ||||
| } | ||||
| 
 | ||||
| body { | ||||
|     font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; | ||||
|     background-color: #f5f5f5; | ||||
| } | ||||
| 
 | ||||
| .container { | ||||
|     display: flex; | ||||
|     height: 100vh; | ||||
| } | ||||
| 
 | ||||
| /* 左侧菜单栏样式 */ | ||||
| .sidebar { | ||||
|     width: 250px; | ||||
|     background-color: #2c3e50; | ||||
|     color: white; | ||||
|     flex-shrink: 0; | ||||
| } | ||||
| 
 | ||||
| .logo { | ||||
|     padding: 20px; | ||||
|     border-bottom: 1px solid #34495e; | ||||
|     text-align: center; | ||||
| } | ||||
| 
 | ||||
| .logo h2 { | ||||
|     color: white; | ||||
|     font-size: 18px; | ||||
| } | ||||
| 
 | ||||
| .menu { | ||||
|     padding: 10px 0; | ||||
| } | ||||
| 
 | ||||
| .menu-item { | ||||
|     margin-bottom: 5px; | ||||
| } | ||||
| 
 | ||||
| .menu-title { | ||||
|     padding: 12px 20px; | ||||
|     cursor: pointer; | ||||
|     display: flex; | ||||
|     justify-content: space-between; | ||||
|     align-items: center; | ||||
|     transition: background-color 0.3s; | ||||
| } | ||||
| 
 | ||||
| .menu-title:hover { | ||||
|     background-color: #34495e; | ||||
| } | ||||
| 
 | ||||
| .arrow { | ||||
|     transition: transform 0.3s; | ||||
|     font-size: 12px; | ||||
| } | ||||
| 
 | ||||
| .arrow.rotated { | ||||
|     transform: rotate(-90deg); | ||||
| } | ||||
| 
 | ||||
| .submenu { | ||||
|     background-color: #34495e; | ||||
|     max-height: 0; | ||||
|     overflow: hidden; | ||||
|     transition: max-height 0.3s ease-out; | ||||
| } | ||||
| 
 | ||||
| .submenu.expanded { | ||||
|     max-height: 200px; | ||||
| } | ||||
| 
 | ||||
| .submenu-item { | ||||
|     padding: 10px 40px; | ||||
|     cursor: pointer; | ||||
|     transition: background-color 0.3s; | ||||
|     border-left: 3px solid transparent; | ||||
| } | ||||
| 
 | ||||
| .submenu-item:hover { | ||||
|     background-color: #3d566e; | ||||
|     border-left-color: #3498db; | ||||
| } | ||||
| 
 | ||||
| /* 中央内容区域样式 */ | ||||
| .main-content { | ||||
|     flex: 1; | ||||
|     display: flex; | ||||
|     flex-direction: column; | ||||
|     background-color: white; | ||||
| } | ||||
| 
 | ||||
| .tab-bar { | ||||
|     background-color: #ecf0f1; | ||||
|     border-bottom: 1px solid #bdc3c7; | ||||
|     display: flex; | ||||
|     padding: 0 10px; | ||||
|     min-height: 40px; | ||||
|     align-items: end; | ||||
| } | ||||
| 
 | ||||
| .tab { | ||||
|     padding: 8px 16px; | ||||
|     background-color: #bdc3c7; | ||||
|     border: 1px solid #95a5a6; | ||||
|     border-bottom: none; | ||||
|     margin-right: 2px; | ||||
|     cursor: pointer; | ||||
|     display: flex; | ||||
|     align-items: center; | ||||
|     min-width: 100px; | ||||
|     border-radius: 4px 4px 0 0; | ||||
|     position: relative; | ||||
| } | ||||
| 
 | ||||
| .tab.active { | ||||
|     background-color: white; | ||||
|     border-color: #bdc3c7; | ||||
|     border-bottom: 1px solid white; | ||||
|     margin-bottom: -1px; | ||||
| } | ||||
| 
 | ||||
| .tab span { | ||||
|     margin-right: 8px; | ||||
| } | ||||
| 
 | ||||
| .tab .close-btn { | ||||
|     background: none; | ||||
|     border: none; | ||||
|     color: #7f8c8d; | ||||
|     cursor: pointer; | ||||
|     font-size: 16px; | ||||
|     padding: 0; | ||||
|     width: 16px; | ||||
|     height: 16px; | ||||
|     display: flex; | ||||
|     align-items: center; | ||||
|     justify-content: center; | ||||
|     border-radius: 2px; | ||||
| } | ||||
| 
 | ||||
| .tab .close-btn:hover { | ||||
|     background-color: #e74c3c; | ||||
|     color: white; | ||||
| } | ||||
| 
 | ||||
| .content-area { | ||||
|     flex: 1; | ||||
|     padding: 20px; | ||||
|     overflow-y: auto; | ||||
| } | ||||
| 
 | ||||
| .tab-content { | ||||
|     display: none; | ||||
| } | ||||
| 
 | ||||
| .tab-content.active { | ||||
|     display: block; | ||||
| } | ||||
| 
 | ||||
| .tab-content h1 { | ||||
|     color: #2c3e50; | ||||
|     margin-bottom: 10px; | ||||
| } | ||||
| 
 | ||||
| .tab-content p { | ||||
|     color: #7f8c8d; | ||||
|     line-height: 1.6; | ||||
| } | ||||
| 
 | ||||
| /* 页面内容样式 */ | ||||
| .page-content { | ||||
|     max-width: 800px; | ||||
| } | ||||
| 
 | ||||
| .page-content h2 { | ||||
|     color: #2c3e50; | ||||
|     margin-bottom: 20px; | ||||
|     padding-bottom: 10px; | ||||
|     border-bottom: 2px solid #3498db; | ||||
| } | ||||
| 
 | ||||
| .form-group { | ||||
|     margin-bottom: 15px; | ||||
| } | ||||
| 
 | ||||
| .form-group label { | ||||
|     display: block; | ||||
|     margin-bottom: 5px; | ||||
|     font-weight: bold; | ||||
|     color: #2c3e50; | ||||
| } | ||||
| 
 | ||||
| .form-group input, | ||||
| .form-group select, | ||||
| .form-group textarea { | ||||
|     width: 100%; | ||||
|     padding: 8px 12px; | ||||
|     border: 1px solid #bdc3c7; | ||||
|     border-radius: 4px; | ||||
|     font-size: 14px; | ||||
| } | ||||
| 
 | ||||
| .btn { | ||||
|     padding: 8px 16px; | ||||
|     border: none; | ||||
|     border-radius: 4px; | ||||
|     cursor: pointer; | ||||
|     font-size: 14px; | ||||
|     margin-right: 10px; | ||||
| } | ||||
| 
 | ||||
| .btn-primary { | ||||
|     background-color: #3498db; | ||||
|     color: white; | ||||
| } | ||||
| 
 | ||||
| .btn-primary:hover { | ||||
|     background-color: #2980b9; | ||||
| } | ||||
| 
 | ||||
| .table { | ||||
|     width: 100%; | ||||
|     border-collapse: collapse; | ||||
|     margin-top: 20px; | ||||
| } | ||||
| 
 | ||||
| .table th, | ||||
| .table td { | ||||
|     padding: 10px; | ||||
|     text-align: left; | ||||
|     border-bottom: 1px solid #ecf0f1; | ||||
| } | ||||
| 
 | ||||
| .table th { | ||||
|     background-color: #f8f9fa; | ||||
|     font-weight: bold; | ||||
|     color: #2c3e50; | ||||
| } | ||||
		Loading…
	
		Reference in New Issue