优惠券添加完毕
This commit is contained in:
parent
b373ae6752
commit
9539fa5658
|
|
@ -1,248 +1,236 @@
|
||||||
# 信息管理系统原型项目
|
# 信息管理系统原型项目
|
||||||
|
|
||||||
|
## 🚨 核心开发约束(必须严格遵守)
|
||||||
|
|
||||||
|
### 文件分离原则
|
||||||
|
1. **HTML内容必须独立存储** - 所有页面内容存储在 `pages/` 目录的独立HTML文件中
|
||||||
|
2. **CSS样式必须独立存储** - 所有样式存储在 `css/` 目录的独立CSS文件中
|
||||||
|
3. **JavaScript功能必须独立存储** - 所有页面功能存储在 `js/` 目录的独立JS文件中
|
||||||
|
|
||||||
|
### 严禁事项 ❌
|
||||||
|
- **禁止在JavaScript中硬编码HTML内容** - 任何HTML标记都不能出现在JS文件中
|
||||||
|
- **禁止在JavaScript中硬编码CSS样式** - 任何CSS样式都不能出现在JS文件中
|
||||||
|
- **禁止在HTML中编写大段JavaScript代码** - 仅允许简单的事件调用
|
||||||
|
- **禁止随意创建新文件** - 优先编辑现有文件,必须创建时需遵循规范
|
||||||
|
- **禁止破坏现有架构模式** - 必须遵循动态加载和模块化原则
|
||||||
|
|
||||||
|
### 必须遵循 ✅
|
||||||
|
- **所有页面内容存储在pages/目录**
|
||||||
|
- **所有页面样式存储在css/目录**
|
||||||
|
- **所有页面功能存储在js/目录**
|
||||||
|
- **JavaScript仅处理逻辑,通过fetch加载HTML和CSS**
|
||||||
|
- **每个JavaScript模块必须包含初始化函数**
|
||||||
|
- **使用中文界面文本**
|
||||||
|
- **遵循文件命名和结构约定**
|
||||||
|
|
||||||
## 项目概述
|
## 项目概述
|
||||||
这是一个传统的中文信息管理系统原型,采用纯HTML/CSS/JavaScript技术栈,实现左侧菜单栏 + 中央tab展示区域的经典布局。项目专注于演示系统架构和交互流程,不追求视觉美观。
|
这是一个传统的中文信息管理系统原型,采用纯HTML/CSS/JavaScript技术栈,实现左侧菜单栏 + 中央tab展示区域的经典布局。项目专注于演示系统架构和交互流程,严格遵循内容、样式、逻辑三分离原则。
|
||||||
|
|
||||||
## 核心架构
|
## 文件结构规范
|
||||||
|
|
||||||
### 技术栈
|
|
||||||
- **前端**: 纯HTML5 + CSS3 + 原生JavaScript ES6+
|
|
||||||
- **架构模式**: 单页应用(SPA) + 动态内容加载
|
|
||||||
- **样式系统**: 自定义CSS,无外部框架依赖
|
|
||||||
- **模块化**: 页面内容与逻辑完全分离
|
|
||||||
|
|
||||||
### 文件结构
|
|
||||||
```
|
```
|
||||||
merchant/
|
merchant/
|
||||||
├── index.html # 主框架页面
|
├── index.html # 主框架页面
|
||||||
├── styles.css # 全局样式文件
|
├── styles.css # 全局样式文件
|
||||||
├── script.js # 核心JavaScript逻辑
|
├── script.js # 核心JavaScript逻辑
|
||||||
|
├── css/ # 专用样式目录
|
||||||
|
│ ├── coupon-modal.css # 优惠券弹窗样式
|
||||||
|
│ └── ... # 其他专用样式
|
||||||
├── js/ # 页面功能模块目录
|
├── js/ # 页面功能模块目录
|
||||||
│ ├── level-settings.js # 等级设置页面功能
|
│ ├── level-settings.js # 等级设置页面功能
|
||||||
│ └── member-view.js # 会员查看页面功能(待创建)
|
│ ├── level-edit.js # 等级编辑页面功能
|
||||||
|
│ └── ... # 其他页面功能
|
||||||
├── pages/ # 页面内容目录
|
├── pages/ # 页面内容目录
|
||||||
│ ├── level-settings.html # 等级设置页面
|
│ ├── level-settings.html # 等级设置页面
|
||||||
│ └── member-view.html # 会员查看页面
|
│ ├── coupon-modal.html # 优惠券弹窗内容
|
||||||
|
│ └── ... # 其他页面内容
|
||||||
└── CLAUDE.md # 项目文档
|
└── CLAUDE.md # 项目文档
|
||||||
```
|
```
|
||||||
|
|
||||||
### 架构特点
|
## 开发流程规范
|
||||||
1. **内容与逻辑分离**: 所有页面内容存储为独立HTML文件
|
|
||||||
2. **模块化JavaScript**: 每个页面的功能逻辑独立存储在对应的JS文件中
|
|
||||||
3. **动态加载**: 使用fetch API异步加载页面内容和对应的JavaScript模块
|
|
||||||
4. **智能初始化**: 自动检测并加载页面对应的JavaScript文件,调用初始化函数
|
|
||||||
5. **Tab管理**: 支持多页面同时打开,可独立关闭
|
|
||||||
6. **菜单系统**: 二级菜单展开/收起,防重复打开
|
|
||||||
|
|
||||||
## 核心功能
|
### 1. 添加新功能的标准流程
|
||||||
|
|
||||||
### 左侧菜单系统
|
#### Step 1: 创建HTML内容文件
|
||||||
- **一级菜单**: 主功能模块入口
|
```bash
|
||||||
- **二级菜单**: 具体功能页面,点击展开/收起
|
# 在pages/目录创建页面内容
|
||||||
- **当前实现**: 会员管理 > 等级设置、会员查看
|
pages/feature-name.html
|
||||||
|
```
|
||||||
|
|
||||||
### 中央Tab系统
|
#### Step 2: 创建CSS样式文件(如需要)
|
||||||
- **多页面管理**: 支持同时打开多个页面tab
|
```bash
|
||||||
- **防重复**: 相同页面不会重复打开,直接激活已存在tab
|
# 在css/目录创建专用样式
|
||||||
- **可关闭**: 每个tab都有独立关闭按钮(首页除外)
|
css/feature-name.css
|
||||||
- **智能切换**: 关闭当前tab时自动激活相邻tab
|
```
|
||||||
|
|
||||||
### 页面加载机制
|
#### Step 3: 创建JavaScript功能文件
|
||||||
- **异步加载**: 使用`fetch`API动态加载HTML内容和JavaScript模块
|
```bash
|
||||||
- **自动检测**: 根据页面名称自动查找对应的JavaScript文件
|
# 在js/目录创建功能逻辑
|
||||||
- **智能缓存**: JavaScript模块避免重复加载,提高性能
|
js/feature-name.js
|
||||||
- **初始化调用**: 自动调用页面对应的初始化函数
|
```
|
||||||
- **错误处理**: 包含完整的加载失败降级方案
|
|
||||||
|
|
||||||
## 开发约束和规范
|
#### Step 4: JavaScript模块标准结构
|
||||||
|
|
||||||
### 重要约束 ⚠️
|
|
||||||
1. **禁止硬编码HTML**: 所有页面内容必须存储在独立的HTML文件中
|
|
||||||
2. **模块化JavaScript**: 每个页面的JavaScript功能必须独立存储在对应的JS文件中
|
|
||||||
3. **优先编辑现有文件**: 禁止随意创建新文件,优先修改现有文件
|
|
||||||
4. **保持架构一致性**: 新页面必须遵循现有的加载和展示模式
|
|
||||||
5. **中文本地化**: 所有界面文本必须使用中文
|
|
||||||
6. **避免内联脚本**: 页面HTML中不应包含大段JavaScript代码
|
|
||||||
|
|
||||||
### JavaScript模块化规范
|
|
||||||
```javascript
|
```javascript
|
||||||
// 页面JavaScript文件结构示例:js/page-name.js
|
// js/feature-name.js
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 页面功能模块
|
* 功能模块名称
|
||||||
* 包含该页面的所有交互逻辑
|
* 功能描述
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// 页面初始化函数(必需)
|
// 页面初始化函数(必需)
|
||||||
function initPageName() {
|
function initFeatureName() {
|
||||||
console.log('页面已初始化');
|
console.log('功能模块已初始化');
|
||||||
// 页面特定的初始化逻辑
|
// 如果需要CSS,动态加载
|
||||||
setupEventListeners();
|
loadFeatureCSS();
|
||||||
|
// 其他初始化逻辑
|
||||||
}
|
}
|
||||||
|
|
||||||
// 页面功能函数
|
// 加载专用CSS(如需要)
|
||||||
|
function loadFeatureCSS() {
|
||||||
|
if (!document.getElementById('featureCSS')) {
|
||||||
|
const link = document.createElement('link');
|
||||||
|
link.id = 'featureCSS';
|
||||||
|
link.rel = 'stylesheet';
|
||||||
|
link.href = 'css/feature-name.css';
|
||||||
|
document.head.appendChild(link);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 功能函数
|
||||||
function someFunction() {
|
function someFunction() {
|
||||||
// 功能实现
|
// 功能实现,仅处理逻辑
|
||||||
|
// 需要HTML时使用fetch加载
|
||||||
}
|
}
|
||||||
|
|
||||||
// 将需要在HTML中调用的函数暴露到全局作用域
|
// 暴露到全局作用域供HTML调用
|
||||||
window.someFunction = someFunction;
|
window.someFunction = someFunction;
|
||||||
|
|
||||||
// 页面清理函数(可选)
|
// 页面清理函数(可选)
|
||||||
function cleanupPageName() {
|
function cleanupFeatureName() {
|
||||||
// 清理事件监听器等
|
// 清理事件监听器等
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 开发规范
|
### 2. 动态内容加载规范
|
||||||
```javascript
|
|
||||||
// 添加新页面的步骤:
|
|
||||||
// 1. 在pages/目录创建对应的HTML文件
|
|
||||||
// 2. 在js/目录创建对应的JavaScript文件
|
|
||||||
// 3. 在HTML中添加新的菜单项,指向该页面
|
|
||||||
// 4. 确保contentType参数与文件名匹配
|
|
||||||
|
|
||||||
// 正确的调用方式:
|
#### HTML内容加载
|
||||||
onclick="openTab('新页面', 'new-page')"
|
```javascript
|
||||||
// 对应文件:
|
// 正确的HTML加载方式
|
||||||
// - pages/new-page.html (页面内容)
|
async function loadHTMLContent() {
|
||||||
// - js/new-page.js (页面功能)
|
try {
|
||||||
|
const response = await fetch('pages/content.html');
|
||||||
|
const htmlContent = await response.text();
|
||||||
|
document.getElementById('container').innerHTML = htmlContent;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('加载失败:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 文件命名规范
|
#### CSS样式加载
|
||||||
- 页面文件:`pages/功能名称.html` (使用kebab-case)
|
```javascript
|
||||||
- JavaScript文件:`js/功能名称.js` (使用kebab-case,与页面文件名保持一致)
|
// 正确的CSS加载方式
|
||||||
- 初始化函数:`init[功能名称CamelCase]()` (自动调用)
|
function loadCSS(cssFile, id) {
|
||||||
- contentType参数:与文件名保持一致
|
if (!document.getElementById(id)) {
|
||||||
- Tab标题:使用中文友好名称
|
const link = document.createElement('link');
|
||||||
|
link.id = id;
|
||||||
## 核心函数说明
|
link.rel = 'stylesheet';
|
||||||
|
link.href = `css/${cssFile}`;
|
||||||
### `openTab(title, contentType)`
|
document.head.appendChild(link);
|
||||||
- **参数**: title(中文标题), contentType(文件名前缀)
|
|
||||||
- **功能**: 创建新tab并异步加载页面内容
|
|
||||||
- **特性**: 防重复打开、错误处理、自动激活
|
|
||||||
|
|
||||||
### `loadPageContent(contentType)`
|
|
||||||
- **参数**: contentType(对应pages/目录下的文件名)
|
|
||||||
- **返回**: Promise<string> HTML内容
|
|
||||||
- **功能**: 异步加载页面HTML内容,并自动加载对应的JavaScript模块
|
|
||||||
- **错误处理**: 加载失败时返回默认提示内容
|
|
||||||
|
|
||||||
### `loadPageScript(contentType)`
|
|
||||||
- **参数**: contentType(对应js/目录下的文件名)
|
|
||||||
- **功能**: 动态加载页面对应的JavaScript文件
|
|
||||||
- **特性**: 避免重复加载,自动调用初始化函数
|
|
||||||
- **命名转换**: 自动将kebab-case转换为CamelCase调用初始化函数
|
|
||||||
|
|
||||||
### `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
|
|
||||||
|
|
||||||
# 在js/目录创建对应JavaScript文件
|
|
||||||
js/function-name.js
|
|
||||||
```
|
|
||||||
|
|
||||||
4. **JavaScript模块结构**:
|
|
||||||
```javascript
|
|
||||||
// js/function-name.js
|
|
||||||
function initFunctionName() {
|
|
||||||
console.log('功能模块已初始化');
|
|
||||||
// 初始化逻辑
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
function someFeature() {
|
### 3. 文件命名规范
|
||||||
// 功能实现
|
- **页面文件**: `pages/功能名称.html` (kebab-case)
|
||||||
}
|
- **样式文件**: `css/功能名称.css` (kebab-case)
|
||||||
|
- **脚本文件**: `js/功能名称.js` (kebab-case)
|
||||||
|
- **初始化函数**: `init[功能名称CamelCase]()`
|
||||||
|
- **CSS ID**: `功能名称CSS` (CamelCase)
|
||||||
|
|
||||||
// 暴露到全局作用域供HTML调用
|
## 架构特点
|
||||||
window.someFeature = someFeature;
|
|
||||||
```
|
|
||||||
|
|
||||||
### 页面内容模板
|
### 三分离原则
|
||||||
|
1. **内容层(HTML)**: 存储页面结构和内容,不包含样式和逻辑
|
||||||
|
2. **表现层(CSS)**: 存储样式定义,不包含内容和逻辑
|
||||||
|
3. **逻辑层(JavaScript)**: 存储交互逻辑,通过API加载内容和样式
|
||||||
|
|
||||||
|
### 动态加载机制
|
||||||
|
- **按需加载**: 只有需要时才加载对应的HTML、CSS、JS
|
||||||
|
- **智能缓存**: 避免重复加载已加载的资源
|
||||||
|
- **错误处理**: 完整的加载失败降级方案
|
||||||
|
- **自动初始化**: 自动调用页面对应的初始化函数
|
||||||
|
|
||||||
|
### 模块化管理
|
||||||
|
- **独立开发**: 每个功能模块可独立开发和维护
|
||||||
|
- **标准接口**: 统一的初始化和清理函数接口
|
||||||
|
- **全局暴露**: 需要在HTML中调用的函数暴露到window对象
|
||||||
|
|
||||||
|
## 核心功能
|
||||||
|
|
||||||
|
### 左侧菜单系统
|
||||||
|
- 一级菜单:主功能模块入口
|
||||||
|
- 二级菜单:具体功能页面,支持展开/收起
|
||||||
|
- 互斥展开:同时只能展开一个子菜单
|
||||||
|
|
||||||
|
### 中央Tab系统
|
||||||
|
- 多页面管理:支持同时打开多个页面tab
|
||||||
|
- 防重复打开:相同页面直接激活已存在tab
|
||||||
|
- 智能关闭:关闭当前tab时自动激活相邻tab
|
||||||
|
|
||||||
|
## 开发示例
|
||||||
|
|
||||||
|
### 弹窗功能示例
|
||||||
|
以优惠券弹窗为例,展示标准的三分离开发模式:
|
||||||
|
|
||||||
|
1. **HTML内容** (`pages/coupon-modal.html`)
|
||||||
```html
|
```html
|
||||||
<div class="page-content">
|
<div id="couponModal" class="modal-overlay">
|
||||||
<h2>页面标题</h2>
|
<div class="modal-content">
|
||||||
|
<!-- 弹窗内容结构 -->
|
||||||
<!-- 表单区域 -->
|
|
||||||
<div class="form-group">
|
|
||||||
<label>字段名称:</label>
|
|
||||||
<input type="text" placeholder="请输入...">
|
|
||||||
</div>
|
</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>
|
</div>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
2. **CSS样式** (`css/coupon-modal.css`)
|
||||||
|
```css
|
||||||
|
.modal-overlay {
|
||||||
|
/* 弹窗样式定义 */
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **JavaScript逻辑** (`js/level-edit.js`)
|
||||||
|
```javascript
|
||||||
|
async function showCouponModal(level) {
|
||||||
|
// 加载CSS
|
||||||
|
loadCouponModalCSS();
|
||||||
|
// 加载HTML
|
||||||
|
const response = await fetch('pages/coupon-modal.html');
|
||||||
|
const modalHtml = await response.text();
|
||||||
|
document.body.insertAdjacentHTML('beforeend', modalHtml);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## 样式系统
|
## 样式系统
|
||||||
|
|
||||||
### CSS类命名规范
|
### 全局样式
|
||||||
- `.page-content`: 页面内容容器
|
- `styles.css`: 基础框架样式
|
||||||
- `.form-group`: 表单字段组
|
- 主题色彩:深蓝色主调,蓝色高亮
|
||||||
- `.btn`, `.btn-primary`: 按钮样式
|
|
||||||
- `.table`: 数据表格
|
|
||||||
- `.menu-item`, `.submenu-item`: 菜单项
|
|
||||||
|
|
||||||
### 主题色彩
|
### 模块样式
|
||||||
- 主色调:深蓝色 `#2c3e50`
|
- 每个功能模块可有独立的CSS文件
|
||||||
- 高亮色:蓝色 `#3498db`
|
- 按需动态加载,避免样式冲突
|
||||||
- 背景色:浅灰 `#f5f5f5`
|
- 使用有意义的CSS类名
|
||||||
- 边框色:灰色 `#bdc3c7`
|
|
||||||
|
|
||||||
## 测试和部署
|
## 技术要求
|
||||||
|
|
||||||
### 本地运行
|
### 运行环境
|
||||||
```bash
|
```bash
|
||||||
# 推荐使用本地HTTP服务器(必需,因为使用了fetch API)
|
# 必须使用HTTP服务器(fetch API要求)
|
||||||
python -m http.server 8000
|
python -m http.server 8000
|
||||||
# 或
|
# 或
|
||||||
npx serve .
|
npx serve .
|
||||||
# 然后访问 http://localhost:8000
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### 浏览器兼容性
|
### 浏览器兼容性
|
||||||
|
|
@ -251,44 +239,20 @@ npx serve .
|
||||||
- Safari 12+
|
- Safari 12+
|
||||||
- Edge 79+
|
- Edge 79+
|
||||||
|
|
||||||
### 快捷键
|
|
||||||
- `ESC`: 关闭当前激活的tab(首页除外)
|
|
||||||
|
|
||||||
## 注意事项
|
|
||||||
|
|
||||||
### 开发限制
|
|
||||||
- ❌ 不要在JavaScript中硬编码HTML内容
|
|
||||||
- ❌ 不要在页面HTML中编写大段JavaScript代码
|
|
||||||
- ❌ 不要随意创建新文件,优先编辑现有文件
|
|
||||||
- ❌ 不要破坏现有的架构模式
|
|
||||||
- ❌ 不要跳过JavaScript模块的初始化函数
|
|
||||||
- ✅ 所有页面内容必须存储在pages/目录
|
|
||||||
- ✅ 所有页面功能必须存储在js/目录对应文件中
|
|
||||||
- ✅ 每个JavaScript模块必须包含初始化函数
|
|
||||||
- ✅ 使用中文界面文本
|
|
||||||
- ✅ 遵循现有的命名和结构约定
|
|
||||||
|
|
||||||
### 技术限制
|
|
||||||
- 必须运行在HTTP服务器环境(不支持file://协议)
|
|
||||||
- 依赖现代浏览器的fetch API和ES6特性
|
|
||||||
- 所有数据都是前端模拟,无后端API集成
|
|
||||||
|
|
||||||
## 项目目标
|
## 项目目标
|
||||||
此项目是一个快速原型系统,用于演示传统管理系统的布局意图和交互流程。专注于功能架构而非视觉设计,为后续开发提供清晰的技术基础和扩展方向。
|
此项目是快速原型系统,用于演示传统管理系统的布局和交互流程。严格遵循内容、样式、逻辑分离原则,为团队协作和后续开发提供清晰的技术基础。
|
||||||
|
|
||||||
## JavaScript模块化架构优势
|
## 开发检查清单
|
||||||
|
|
||||||
### 维护性
|
在开发任何功能前,请确认:
|
||||||
- **代码分离**: 每个页面的功能逻辑独立,便于维护和调试
|
|
||||||
- **模块清晰**: 避免全局script.js文件过于庞大
|
|
||||||
- **团队协作**: 不同开发者可以独立开发不同页面的功能
|
|
||||||
|
|
||||||
### 性能优化
|
- [ ] 是否创建了独立的HTML文件存储内容?
|
||||||
- **按需加载**: 只有打开页面时才加载对应的JavaScript文件
|
- [ ] 是否创建了独立的CSS文件存储样式?
|
||||||
- **避免重复**: 已加载的模块不会重复加载
|
- [ ] JavaScript中是否避免了硬编码HTML和CSS?
|
||||||
- **内存管理**: 可以在页面关闭时进行资源清理
|
- [ ] 是否使用fetch API动态加载内容和样式?
|
||||||
|
- [ ] 是否包含了初始化函数?
|
||||||
|
- [ ] 是否将需要调用的函数暴露到全局作用域?
|
||||||
|
- [ ] 文件命名是否遵循kebab-case规范?
|
||||||
|
- [ ] 是否使用了中文界面文本?
|
||||||
|
|
||||||
### 可扩展性
|
**记住:内容、样式、逻辑三分离是本项目的核心原则,违反此原则的代码不被接受。**
|
||||||
- **标准化流程**: 新增页面功能有明确的开发流程
|
|
||||||
- **自动化集成**: 新JavaScript模块会被系统自动检测和加载
|
|
||||||
- **灵活扩展**: 可以轻松为现有页面添加新功能
|
|
||||||
|
|
@ -0,0 +1,123 @@
|
||||||
|
.modal-overlay {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: rgba(0, 0, 0, 0.5);
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
z-index: 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-content {
|
||||||
|
background: white;
|
||||||
|
border-radius: 8px;
|
||||||
|
width: 400px;
|
||||||
|
max-width: 90vw;
|
||||||
|
max-height: 90vh;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: 20px;
|
||||||
|
border-bottom: 1px solid #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-header h3 {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 18px;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-close {
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
font-size: 24px;
|
||||||
|
cursor: pointer;
|
||||||
|
color: #999;
|
||||||
|
padding: 0;
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-close:hover {
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-body {
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-footer {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
gap: 10px;
|
||||||
|
padding: 20px;
|
||||||
|
border-top: 1px solid #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group label {
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.required {
|
||||||
|
color: #e74c3c;
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-with-dropdown {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-with-dropdown .form-input {
|
||||||
|
flex: 1;
|
||||||
|
padding-right: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-btn {
|
||||||
|
position: absolute;
|
||||||
|
right: 8px;
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
color: #666;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-secondary {
|
||||||
|
background-color: #f8f9fa;
|
||||||
|
color: #6c757d;
|
||||||
|
border: 1px solid #dee2e6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-secondary:hover {
|
||||||
|
background-color: #e9ecef;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary {
|
||||||
|
background-color: #007bff;
|
||||||
|
color: white;
|
||||||
|
border: 1px solid #007bff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary:hover {
|
||||||
|
background-color: #0056b3;
|
||||||
|
}
|
||||||
|
|
@ -192,7 +192,73 @@ function updateEditTable(editData) {
|
||||||
|
|
||||||
// 添加优惠券功能
|
// 添加优惠券功能
|
||||||
function addCoupon(level) {
|
function addCoupon(level) {
|
||||||
alert(`为${level}添加生日优惠券功能开发中...`);
|
showCouponModal(level);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 显示优惠券添加弹窗
|
||||||
|
async function showCouponModal(level) {
|
||||||
|
try {
|
||||||
|
// 加载CSS样式
|
||||||
|
loadCouponModalCSS();
|
||||||
|
|
||||||
|
// 加载HTML内容
|
||||||
|
const response = await fetch('pages/coupon-modal.html');
|
||||||
|
const modalHtml = await response.text();
|
||||||
|
|
||||||
|
// 添加到页面
|
||||||
|
document.body.insertAdjacentHTML('beforeend', modalHtml);
|
||||||
|
|
||||||
|
// 存储当前等级信息
|
||||||
|
window.currentCouponLevel = level;
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('加载优惠券弹窗失败:', error);
|
||||||
|
alert('加载弹窗失败,请重试');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载优惠券弹窗CSS
|
||||||
|
function loadCouponModalCSS() {
|
||||||
|
if (!document.getElementById('couponModalCSS')) {
|
||||||
|
const link = document.createElement('link');
|
||||||
|
link.id = 'couponModalCSS';
|
||||||
|
link.rel = 'stylesheet';
|
||||||
|
link.href = 'css/coupon-modal.css';
|
||||||
|
document.head.appendChild(link);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关闭优惠券弹窗
|
||||||
|
function closeCouponModal() {
|
||||||
|
const modal = document.getElementById('couponModal');
|
||||||
|
if (modal) {
|
||||||
|
modal.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 确认添加优惠券
|
||||||
|
function confirmAddCoupon() {
|
||||||
|
const couponName = document.getElementById('couponName').value;
|
||||||
|
const threshold = document.getElementById('couponThreshold').value;
|
||||||
|
const discount = document.getElementById('couponDiscount').value;
|
||||||
|
const validity = document.getElementById('couponValidity').value;
|
||||||
|
const level = window.currentCouponLevel;
|
||||||
|
|
||||||
|
if (!couponName.trim()) {
|
||||||
|
alert('请输入优惠券名称');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('添加优惠券:', {
|
||||||
|
level: level,
|
||||||
|
name: couponName,
|
||||||
|
threshold: threshold,
|
||||||
|
discount: discount,
|
||||||
|
validity: validity
|
||||||
|
});
|
||||||
|
|
||||||
|
alert(`已为${level}添加优惠券"${couponName}"`);
|
||||||
|
closeCouponModal();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 保存等级编辑
|
// 保存等级编辑
|
||||||
|
|
@ -232,6 +298,8 @@ function collectFormData() {
|
||||||
// 将需要在HTML中调用的函数暴露到全局作用域
|
// 将需要在HTML中调用的函数暴露到全局作用域
|
||||||
window.addCoupon = addCoupon;
|
window.addCoupon = addCoupon;
|
||||||
window.saveLevelEdit = saveLevelEdit;
|
window.saveLevelEdit = saveLevelEdit;
|
||||||
|
window.closeCouponModal = closeCouponModal;
|
||||||
|
window.confirmAddCoupon = confirmAddCoupon;
|
||||||
|
|
||||||
// 页面清理函数(可选)
|
// 页面清理函数(可选)
|
||||||
function cleanupLevelEdit() {
|
function cleanupLevelEdit() {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
<div id="couponModal" class="modal-overlay">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h3>添加优惠券</h3>
|
||||||
|
<button class="modal-close" onclick="closeCouponModal()">×</button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<div class="form-group">
|
||||||
|
<label><span class="required">*</span> 优惠券名称</label>
|
||||||
|
<input type="text" id="couponName" placeholder="生日优惠券" class="form-input">
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label><span class="required">*</span> 优惠券门槛金额</label>
|
||||||
|
<div class="input-with-dropdown">
|
||||||
|
<input type="number" id="couponThreshold" value="10" class="form-input">
|
||||||
|
<button class="dropdown-btn">▼</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label><span class="required">*</span> 优惠券减免金额</label>
|
||||||
|
<div class="input-with-dropdown">
|
||||||
|
<input type="number" id="couponDiscount" value="1" class="form-input">
|
||||||
|
<button class="dropdown-btn">▼</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label><span class="required">*</span> 优惠券有效时间</label>
|
||||||
|
<div class="input-with-dropdown">
|
||||||
|
<input type="number" id="couponValidity" value="1" class="form-input">
|
||||||
|
<button class="dropdown-btn">▼</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button class="btn btn-secondary" onclick="closeCouponModal()">取消</button>
|
||||||
|
<button class="btn btn-primary" onclick="confirmAddCoupon()">确认添加</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
Loading…
Reference in New Issue