使用new_web来逐步构建
This commit is contained in:
parent
e6065a5f8f
commit
b373ae6752
|
|
@ -17,6 +17,9 @@ merchant/
|
||||||
├── index.html # 主框架页面
|
├── index.html # 主框架页面
|
||||||
├── styles.css # 全局样式文件
|
├── styles.css # 全局样式文件
|
||||||
├── script.js # 核心JavaScript逻辑
|
├── script.js # 核心JavaScript逻辑
|
||||||
|
├── js/ # 页面功能模块目录
|
||||||
|
│ ├── level-settings.js # 等级设置页面功能
|
||||||
|
│ └── member-view.js # 会员查看页面功能(待创建)
|
||||||
├── pages/ # 页面内容目录
|
├── pages/ # 页面内容目录
|
||||||
│ ├── level-settings.html # 等级设置页面
|
│ ├── level-settings.html # 等级设置页面
|
||||||
│ └── member-view.html # 会员查看页面
|
│ └── member-view.html # 会员查看页面
|
||||||
|
|
@ -25,9 +28,11 @@ merchant/
|
||||||
|
|
||||||
### 架构特点
|
### 架构特点
|
||||||
1. **内容与逻辑分离**: 所有页面内容存储为独立HTML文件
|
1. **内容与逻辑分离**: 所有页面内容存储为独立HTML文件
|
||||||
2. **动态加载**: 使用fetch API异步加载页面内容
|
2. **模块化JavaScript**: 每个页面的功能逻辑独立存储在对应的JS文件中
|
||||||
3. **Tab管理**: 支持多页面同时打开,可独立关闭
|
3. **动态加载**: 使用fetch API异步加载页面内容和对应的JavaScript模块
|
||||||
4. **菜单系统**: 二级菜单展开/收起,防重复打开
|
4. **智能初始化**: 自动检测并加载页面对应的JavaScript文件,调用初始化函数
|
||||||
|
5. **Tab管理**: 支持多页面同时打开,可独立关闭
|
||||||
|
6. **菜单系统**: 二级菜单展开/收起,防重复打开
|
||||||
|
|
||||||
## 核心功能
|
## 核心功能
|
||||||
|
|
||||||
|
|
@ -43,32 +48,71 @@ merchant/
|
||||||
- **智能切换**: 关闭当前tab时自动激活相邻tab
|
- **智能切换**: 关闭当前tab时自动激活相邻tab
|
||||||
|
|
||||||
### 页面加载机制
|
### 页面加载机制
|
||||||
- **异步加载**: 使用`fetch`API动态加载HTML内容
|
- **异步加载**: 使用`fetch`API动态加载HTML内容和JavaScript模块
|
||||||
|
- **自动检测**: 根据页面名称自动查找对应的JavaScript文件
|
||||||
|
- **智能缓存**: JavaScript模块避免重复加载,提高性能
|
||||||
|
- **初始化调用**: 自动调用页面对应的初始化函数
|
||||||
- **错误处理**: 包含完整的加载失败降级方案
|
- **错误处理**: 包含完整的加载失败降级方案
|
||||||
- **缓存管理**: 每次点击都重新加载,保证内容最新
|
|
||||||
|
|
||||||
## 开发约束和规范
|
## 开发约束和规范
|
||||||
|
|
||||||
### 重要约束 ⚠️
|
### 重要约束 ⚠️
|
||||||
1. **禁止硬编码HTML**: 所有页面内容必须存储在独立的HTML文件中
|
1. **禁止硬编码HTML**: 所有页面内容必须存储在独立的HTML文件中
|
||||||
2. **优先编辑现有文件**: 禁止随意创建新文件,优先修改现有文件
|
2. **模块化JavaScript**: 每个页面的JavaScript功能必须独立存储在对应的JS文件中
|
||||||
3. **保持架构一致性**: 新页面必须遵循现有的加载和展示模式
|
3. **优先编辑现有文件**: 禁止随意创建新文件,优先修改现有文件
|
||||||
4. **中文本地化**: 所有界面文本必须使用中文
|
4. **保持架构一致性**: 新页面必须遵循现有的加载和展示模式
|
||||||
|
5. **中文本地化**: 所有界面文本必须使用中文
|
||||||
|
6. **避免内联脚本**: 页面HTML中不应包含大段JavaScript代码
|
||||||
|
|
||||||
|
### JavaScript模块化规范
|
||||||
|
```javascript
|
||||||
|
// 页面JavaScript文件结构示例:js/page-name.js
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 页面功能模块
|
||||||
|
* 包含该页面的所有交互逻辑
|
||||||
|
*/
|
||||||
|
|
||||||
|
// 页面初始化函数(必需)
|
||||||
|
function initPageName() {
|
||||||
|
console.log('页面已初始化');
|
||||||
|
// 页面特定的初始化逻辑
|
||||||
|
setupEventListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 页面功能函数
|
||||||
|
function someFunction() {
|
||||||
|
// 功能实现
|
||||||
|
}
|
||||||
|
|
||||||
|
// 将需要在HTML中调用的函数暴露到全局作用域
|
||||||
|
window.someFunction = someFunction;
|
||||||
|
|
||||||
|
// 页面清理函数(可选)
|
||||||
|
function cleanupPageName() {
|
||||||
|
// 清理事件监听器等
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### 开发规范
|
### 开发规范
|
||||||
```javascript
|
```javascript
|
||||||
// 添加新页面的步骤:
|
// 添加新页面的步骤:
|
||||||
// 1. 在pages/目录创建对应的HTML文件
|
// 1. 在pages/目录创建对应的HTML文件
|
||||||
// 2. 在HTML中添加新的菜单项,指向该页面
|
// 2. 在js/目录创建对应的JavaScript文件
|
||||||
// 3. 确保contentType参数与文件名匹配
|
// 3. 在HTML中添加新的菜单项,指向该页面
|
||||||
|
// 4. 确保contentType参数与文件名匹配
|
||||||
|
|
||||||
// 正确的调用方式:
|
// 正确的调用方式:
|
||||||
onclick="openTab('新页面', 'new-page')"
|
onclick="openTab('新页面', 'new-page')"
|
||||||
// 对应文件:pages/new-page.html
|
// 对应文件:
|
||||||
|
// - pages/new-page.html (页面内容)
|
||||||
|
// - js/new-page.js (页面功能)
|
||||||
```
|
```
|
||||||
|
|
||||||
### 文件命名规范
|
### 文件命名规范
|
||||||
- 页面文件:`pages/功能名称.html` (使用kebab-case)
|
- 页面文件:`pages/功能名称.html` (使用kebab-case)
|
||||||
|
- JavaScript文件:`js/功能名称.js` (使用kebab-case,与页面文件名保持一致)
|
||||||
|
- 初始化函数:`init[功能名称CamelCase]()` (自动调用)
|
||||||
- contentType参数:与文件名保持一致
|
- contentType参数:与文件名保持一致
|
||||||
- Tab标题:使用中文友好名称
|
- Tab标题:使用中文友好名称
|
||||||
|
|
||||||
|
|
@ -82,8 +126,15 @@ onclick="openTab('新页面', 'new-page')"
|
||||||
### `loadPageContent(contentType)`
|
### `loadPageContent(contentType)`
|
||||||
- **参数**: contentType(对应pages/目录下的文件名)
|
- **参数**: contentType(对应pages/目录下的文件名)
|
||||||
- **返回**: Promise<string> HTML内容
|
- **返回**: Promise<string> HTML内容
|
||||||
|
- **功能**: 异步加载页面HTML内容,并自动加载对应的JavaScript模块
|
||||||
- **错误处理**: 加载失败时返回默认提示内容
|
- **错误处理**: 加载失败时返回默认提示内容
|
||||||
|
|
||||||
|
### `loadPageScript(contentType)`
|
||||||
|
- **参数**: contentType(对应js/目录下的文件名)
|
||||||
|
- **功能**: 动态加载页面对应的JavaScript文件
|
||||||
|
- **特性**: 避免重复加载,自动调用初始化函数
|
||||||
|
- **命名转换**: 自动将kebab-case转换为CamelCase调用初始化函数
|
||||||
|
|
||||||
### `toggleSubmenu(submenuId)`
|
### `toggleSubmenu(submenuId)`
|
||||||
- **参数**: submenuId(子菜单DOM元素ID)
|
- **参数**: submenuId(子菜单DOM元素ID)
|
||||||
- **功能**: 切换子菜单展开/收起状态
|
- **功能**: 切换子菜单展开/收起状态
|
||||||
|
|
@ -112,10 +163,29 @@ onclick="openTab('新页面', 'new-page')"
|
||||||
</div>
|
</div>
|
||||||
```
|
```
|
||||||
|
|
||||||
3. **创建页面内容**:
|
3. **创建页面内容和功能**:
|
||||||
```bash
|
```bash
|
||||||
# 在pages/目录创建对应HTML文件
|
# 在pages/目录创建对应HTML文件
|
||||||
pages/function-name.html
|
pages/function-name.html
|
||||||
|
|
||||||
|
# 在js/目录创建对应JavaScript文件
|
||||||
|
js/function-name.js
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **JavaScript模块结构**:
|
||||||
|
```javascript
|
||||||
|
// js/function-name.js
|
||||||
|
function initFunctionName() {
|
||||||
|
console.log('功能模块已初始化');
|
||||||
|
// 初始化逻辑
|
||||||
|
}
|
||||||
|
|
||||||
|
function someFeature() {
|
||||||
|
// 功能实现
|
||||||
|
}
|
||||||
|
|
||||||
|
// 暴露到全局作用域供HTML调用
|
||||||
|
window.someFeature = someFeature;
|
||||||
```
|
```
|
||||||
|
|
||||||
### 页面内容模板
|
### 页面内容模板
|
||||||
|
|
@ -188,9 +258,13 @@ npx serve .
|
||||||
|
|
||||||
### 开发限制
|
### 开发限制
|
||||||
- ❌ 不要在JavaScript中硬编码HTML内容
|
- ❌ 不要在JavaScript中硬编码HTML内容
|
||||||
|
- ❌ 不要在页面HTML中编写大段JavaScript代码
|
||||||
- ❌ 不要随意创建新文件,优先编辑现有文件
|
- ❌ 不要随意创建新文件,优先编辑现有文件
|
||||||
- ❌ 不要破坏现有的架构模式
|
- ❌ 不要破坏现有的架构模式
|
||||||
|
- ❌ 不要跳过JavaScript模块的初始化函数
|
||||||
- ✅ 所有页面内容必须存储在pages/目录
|
- ✅ 所有页面内容必须存储在pages/目录
|
||||||
|
- ✅ 所有页面功能必须存储在js/目录对应文件中
|
||||||
|
- ✅ 每个JavaScript模块必须包含初始化函数
|
||||||
- ✅ 使用中文界面文本
|
- ✅ 使用中文界面文本
|
||||||
- ✅ 遵循现有的命名和结构约定
|
- ✅ 遵循现有的命名和结构约定
|
||||||
|
|
||||||
|
|
@ -201,3 +275,20 @@ npx serve .
|
||||||
|
|
||||||
## 项目目标
|
## 项目目标
|
||||||
此项目是一个快速原型系统,用于演示传统管理系统的布局意图和交互流程。专注于功能架构而非视觉设计,为后续开发提供清晰的技术基础和扩展方向。
|
此项目是一个快速原型系统,用于演示传统管理系统的布局意图和交互流程。专注于功能架构而非视觉设计,为后续开发提供清晰的技术基础和扩展方向。
|
||||||
|
|
||||||
|
## JavaScript模块化架构优势
|
||||||
|
|
||||||
|
### 维护性
|
||||||
|
- **代码分离**: 每个页面的功能逻辑独立,便于维护和调试
|
||||||
|
- **模块清晰**: 避免全局script.js文件过于庞大
|
||||||
|
- **团队协作**: 不同开发者可以独立开发不同页面的功能
|
||||||
|
|
||||||
|
### 性能优化
|
||||||
|
- **按需加载**: 只有打开页面时才加载对应的JavaScript文件
|
||||||
|
- **避免重复**: 已加载的模块不会重复加载
|
||||||
|
- **内存管理**: 可以在页面关闭时进行资源清理
|
||||||
|
|
||||||
|
### 可扩展性
|
||||||
|
- **标准化流程**: 新增页面功能有明确的开发流程
|
||||||
|
- **自动化集成**: 新JavaScript模块会被系统自动检测和加载
|
||||||
|
- **灵活扩展**: 可以轻松为现有页面添加新功能
|
||||||
|
|
@ -0,0 +1,128 @@
|
||||||
|
/**
|
||||||
|
* 等级明细页面功能模块
|
||||||
|
* 包含该页面的所有交互逻辑
|
||||||
|
*/
|
||||||
|
|
||||||
|
// 模拟不同商户的等级数据
|
||||||
|
const merchantLevelData = {
|
||||||
|
'牛牛蔬菜店': [
|
||||||
|
{ level: 'LV1', growth: 100, members: 1250, benefits: '9.5折优惠' },
|
||||||
|
{ level: 'LV2', growth: 500, members: 850, benefits: '9折优惠, 积分双倍' },
|
||||||
|
{ level: 'LV3', growth: 1200, members: 450, benefits: '8.5折优惠, 积分双倍, 生日优惠券' },
|
||||||
|
{ level: 'LV4', growth: 2500, members: 180, benefits: '8折优惠, 积分三倍, 生日优惠券, 专属客服' }
|
||||||
|
],
|
||||||
|
'羊羊水果店': [
|
||||||
|
{ level: 'LV1', growth: 80, members: 980, benefits: '9.8折优惠' },
|
||||||
|
{ level: 'LV2', growth: 400, members: 650, benefits: '9.2折优惠, 积分双倍' },
|
||||||
|
{ level: 'LV3', growth: 1000, members: 320, benefits: '8.8折优惠, 积分双倍, 生日优惠券' }
|
||||||
|
],
|
||||||
|
'小狗羊肉': [
|
||||||
|
{ level: 'LV1', growth: 120, members: 800, benefits: '9.3折优惠' },
|
||||||
|
{ level: 'LV2', growth: 600, members: 520, benefits: '8.8折优惠, 积分双倍' },
|
||||||
|
{ level: 'LV3', growth: 1500, members: 280, benefits: '8.3折优惠, 积分双倍, 生日优惠券' },
|
||||||
|
{ level: 'LV4', growth: 3000, members: 120, benefits: '7.8折优惠, 积分三倍, 生日优惠券, 专属客服' }
|
||||||
|
],
|
||||||
|
'小马猪蹄': [
|
||||||
|
{ level: 'LV1', growth: 150, members: 600, benefits: '9.5折优惠' },
|
||||||
|
{ level: 'LV2', growth: 800, members: 350, benefits: '9折优惠, 积分双倍' }
|
||||||
|
],
|
||||||
|
'小鱼生鲜': [
|
||||||
|
{ level: 'LV1', growth: 90, members: 1100, benefits: '9.6折优惠' },
|
||||||
|
{ level: 'LV2', growth: 450, members: 750, benefits: '9.1折优惠, 积分双倍' },
|
||||||
|
{ level: 'LV3', growth: 1100, members: 400, benefits: '8.6折优惠, 积分双倍, 生日优惠券' },
|
||||||
|
{ level: 'LV4', growth: 2200, members: 200, benefits: '8.1折优惠, 积分三倍, 生日优惠券, 专属客服' }
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
// 页面初始化函数(必需)
|
||||||
|
function initLevelDetails() {
|
||||||
|
console.log('等级明细页面已初始化');
|
||||||
|
|
||||||
|
// 从URL参数或全局变量获取商户名称
|
||||||
|
const merchantName = getCurrentMerchantName();
|
||||||
|
if (merchantName) {
|
||||||
|
updatePageContent(merchantName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取当前商户名称
|
||||||
|
function getCurrentMerchantName() {
|
||||||
|
// 可以从tab标题中提取商户名称
|
||||||
|
const activeTab = document.querySelector('.tab.active');
|
||||||
|
if (activeTab) {
|
||||||
|
const tabTitle = activeTab.textContent.trim();
|
||||||
|
// 提取商户名称(去掉" - 等级设置明细"后缀)
|
||||||
|
const merchantName = tabTitle.replace(' - 等级设置明细', '');
|
||||||
|
// 如果标题中包含了商户名称,则返回商户名称
|
||||||
|
if (merchantName !== tabTitle) {
|
||||||
|
return merchantName;
|
||||||
|
}
|
||||||
|
// 否则尝试从关闭按钮的 × 前面获取标题文本
|
||||||
|
const tabTextContent = activeTab.querySelector('.tab-text');
|
||||||
|
if (tabTextContent) {
|
||||||
|
return tabTextContent.textContent.replace(' - 等级设置明细', '');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return '时尚服装店'; // 默认值
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新页面内容
|
||||||
|
function updatePageContent(merchantName) {
|
||||||
|
// 更新页面标题
|
||||||
|
const merchantNameElement = document.getElementById('merchantName');
|
||||||
|
if (merchantNameElement) {
|
||||||
|
merchantNameElement.textContent = merchantName;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新表格数据
|
||||||
|
const levelData = merchantLevelData[merchantName];
|
||||||
|
if (levelData) {
|
||||||
|
updateLevelTable(levelData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新等级表格数据
|
||||||
|
function updateLevelTable(levelData) {
|
||||||
|
const tbody = document.getElementById('levelDetailsBody');
|
||||||
|
if (!tbody) return;
|
||||||
|
|
||||||
|
tbody.innerHTML = '';
|
||||||
|
|
||||||
|
levelData.forEach(level => {
|
||||||
|
const row = document.createElement('tr');
|
||||||
|
row.innerHTML = `
|
||||||
|
<td>${level.level}</td>
|
||||||
|
<td>${level.growth}</td>
|
||||||
|
<td>${level.members}</td>
|
||||||
|
<td>${level.benefits}</td>
|
||||||
|
`;
|
||||||
|
tbody.appendChild(row);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 等级编辑功能
|
||||||
|
function addLevel() {
|
||||||
|
// 获取当前商户名称
|
||||||
|
const merchantName = getCurrentMerchantName();
|
||||||
|
// 打开新的tab页面显示该商户的等级编辑
|
||||||
|
const tabTitle = `${merchantName} - 等级编辑`;
|
||||||
|
if (typeof window.openTab === 'function') {
|
||||||
|
window.openTab(tabTitle, 'level-edit');
|
||||||
|
} else {
|
||||||
|
console.error('openTab函数未找到');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 保存等级设置
|
||||||
|
function saveLevelSettings() {
|
||||||
|
alert('等级设置已保存!');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 将需要在HTML中调用的函数暴露到全局作用域
|
||||||
|
window.addLevel = addLevel;
|
||||||
|
window.saveLevelSettings = saveLevelSettings;
|
||||||
|
|
||||||
|
// 页面清理函数(可选)
|
||||||
|
function cleanupLevelDetails() {
|
||||||
|
// 清理事件监听器等
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,239 @@
|
||||||
|
/**
|
||||||
|
* 等级编辑页面功能模块
|
||||||
|
* 包含该页面的所有交互逻辑
|
||||||
|
*/
|
||||||
|
|
||||||
|
// 模拟不同商户的等级编辑数据
|
||||||
|
const merchantEditData = {
|
||||||
|
'牛牛蔬菜店': [
|
||||||
|
{
|
||||||
|
level: 'LV1',
|
||||||
|
name: '铜牌会员',
|
||||||
|
growthStart: 0,
|
||||||
|
growthEnd: 100,
|
||||||
|
discountEnabled: true,
|
||||||
|
discountRate: 5,
|
||||||
|
pointsEnabled: false,
|
||||||
|
birthdayCouponEnabled: false,
|
||||||
|
birthdayPointsEnabled: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
level: 'LV2',
|
||||||
|
name: '银牌会员',
|
||||||
|
growthStart: 101,
|
||||||
|
growthEnd: 500,
|
||||||
|
discountEnabled: true,
|
||||||
|
discountRate: 10,
|
||||||
|
pointsEnabled: true,
|
||||||
|
birthdayCouponEnabled: true,
|
||||||
|
birthdayPointsEnabled: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
level: 'LV3',
|
||||||
|
name: '金牌会员',
|
||||||
|
growthStart: 501,
|
||||||
|
growthEnd: 1200,
|
||||||
|
discountEnabled: true,
|
||||||
|
discountRate: 15,
|
||||||
|
pointsEnabled: true,
|
||||||
|
birthdayCouponEnabled: true,
|
||||||
|
birthdayPointsEnabled: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
level: 'LV4',
|
||||||
|
name: '钻石会员',
|
||||||
|
growthStart: 1201,
|
||||||
|
growthEnd: 9999,
|
||||||
|
discountEnabled: true,
|
||||||
|
discountRate: 20,
|
||||||
|
pointsEnabled: true,
|
||||||
|
birthdayCouponEnabled: true,
|
||||||
|
birthdayPointsEnabled: true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'羊羊水果店': [
|
||||||
|
{
|
||||||
|
level: 'LV1',
|
||||||
|
name: '普通会员',
|
||||||
|
growthStart: 0,
|
||||||
|
growthEnd: 80,
|
||||||
|
discountEnabled: true,
|
||||||
|
discountRate: 2,
|
||||||
|
pointsEnabled: false,
|
||||||
|
birthdayCouponEnabled: false,
|
||||||
|
birthdayPointsEnabled: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
level: 'LV2',
|
||||||
|
name: '优质会员',
|
||||||
|
growthStart: 81,
|
||||||
|
growthEnd: 400,
|
||||||
|
discountEnabled: true,
|
||||||
|
discountRate: 8,
|
||||||
|
pointsEnabled: true,
|
||||||
|
birthdayCouponEnabled: false,
|
||||||
|
birthdayPointsEnabled: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
level: 'LV3',
|
||||||
|
name: '贵宾会员',
|
||||||
|
growthStart: 401,
|
||||||
|
growthEnd: 1000,
|
||||||
|
discountEnabled: true,
|
||||||
|
discountRate: 12,
|
||||||
|
pointsEnabled: true,
|
||||||
|
birthdayCouponEnabled: true,
|
||||||
|
birthdayPointsEnabled: true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
// 页面初始化函数(必需)
|
||||||
|
function initLevelEdit() {
|
||||||
|
console.log('等级编辑页面已初始化');
|
||||||
|
|
||||||
|
// 从URL参数或全局变量获取商户名称
|
||||||
|
const merchantName = getCurrentMerchantName();
|
||||||
|
if (merchantName) {
|
||||||
|
updateEditPageContent(merchantName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取当前商户名称
|
||||||
|
function getCurrentMerchantName() {
|
||||||
|
// 可以从tab标题中提取商户名称
|
||||||
|
const activeTab = document.querySelector('.tab.active');
|
||||||
|
if (activeTab) {
|
||||||
|
const tabTitle = activeTab.textContent.trim();
|
||||||
|
// 提取商户名称(去掉" - 等级编辑"后缀)
|
||||||
|
const merchantName = tabTitle.replace(' - 等级编辑', '');
|
||||||
|
// 如果标题中包含了商户名称,则返回商户名称
|
||||||
|
if (merchantName !== tabTitle) {
|
||||||
|
return merchantName;
|
||||||
|
}
|
||||||
|
// 否则尝试从关闭按钮的 × 前面获取标题文本
|
||||||
|
const tabTextContent = activeTab.querySelector('.tab-text');
|
||||||
|
if (tabTextContent) {
|
||||||
|
return tabTextContent.textContent.replace(' - 等级编辑', '');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return '时尚服装店'; // 默认值
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新页面内容
|
||||||
|
function updateEditPageContent(merchantName) {
|
||||||
|
// 更新页面标题
|
||||||
|
const merchantNameElement = document.getElementById('merchantName');
|
||||||
|
if (merchantNameElement) {
|
||||||
|
merchantNameElement.textContent = merchantName;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新表格数据
|
||||||
|
const editData = merchantEditData[merchantName];
|
||||||
|
if (editData) {
|
||||||
|
updateEditTable(editData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新编辑表格数据
|
||||||
|
function updateEditTable(editData) {
|
||||||
|
const tbody = document.getElementById('levelEditBody');
|
||||||
|
if (!tbody) return;
|
||||||
|
|
||||||
|
tbody.innerHTML = '';
|
||||||
|
|
||||||
|
editData.forEach(level => {
|
||||||
|
const row = document.createElement('tr');
|
||||||
|
row.innerHTML = `
|
||||||
|
<td>${level.level}</td>
|
||||||
|
<td>
|
||||||
|
<input type="text" value="${level.name}" class="form-input">
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div class="range-input">
|
||||||
|
<input type="number" value="${level.growthStart}" class="form-input range-start"> -
|
||||||
|
<input type="number" value="${level.growthEnd}" class="form-input range-end">
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<label class="switch">
|
||||||
|
<input type="checkbox" ${level.discountEnabled ? 'checked' : ''}>
|
||||||
|
<span class="slider"></span>
|
||||||
|
</label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input type="number" value="${level.discountRate}" class="form-input discount-input">
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<label class="switch">
|
||||||
|
<input type="checkbox" ${level.pointsEnabled ? 'checked' : ''}>
|
||||||
|
<span class="slider"></span>
|
||||||
|
</label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<label class="switch">
|
||||||
|
<input type="checkbox" ${level.birthdayCouponEnabled ? 'checked' : ''}>
|
||||||
|
<span class="slider"></span>
|
||||||
|
</label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<button class="btn btn-action" onclick="addCoupon('${level.level}')">添加优惠券</button>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<label class="switch">
|
||||||
|
<input type="checkbox" ${level.birthdayPointsEnabled ? 'checked' : ''}>
|
||||||
|
<span class="slider"></span>
|
||||||
|
</label>
|
||||||
|
</td>
|
||||||
|
`;
|
||||||
|
tbody.appendChild(row);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加优惠券功能
|
||||||
|
function addCoupon(level) {
|
||||||
|
alert(`为${level}添加生日优惠券功能开发中...`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 保存等级编辑
|
||||||
|
function saveLevelEdit() {
|
||||||
|
// 收集表单数据
|
||||||
|
const formData = collectFormData();
|
||||||
|
console.log('保存的等级编辑数据:', formData);
|
||||||
|
alert('等级编辑设置已保存!');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 收集表单数据
|
||||||
|
function collectFormData() {
|
||||||
|
const tbody = document.getElementById('levelEditBody');
|
||||||
|
if (!tbody) return [];
|
||||||
|
|
||||||
|
const rows = tbody.querySelectorAll('tr');
|
||||||
|
const data = [];
|
||||||
|
|
||||||
|
rows.forEach((row, index) => {
|
||||||
|
const levelData = {
|
||||||
|
level: row.cells[0].textContent,
|
||||||
|
name: row.querySelector('input[type="text"]').value,
|
||||||
|
growthStart: parseInt(row.querySelector('.range-start').value),
|
||||||
|
growthEnd: parseInt(row.querySelector('.range-end').value),
|
||||||
|
discountEnabled: row.querySelectorAll('input[type="checkbox"]')[0].checked,
|
||||||
|
discountRate: parseInt(row.querySelector('.discount-input').value),
|
||||||
|
pointsEnabled: row.querySelectorAll('input[type="checkbox"]')[1].checked,
|
||||||
|
birthdayCouponEnabled: row.querySelectorAll('input[type="checkbox"]')[2].checked,
|
||||||
|
birthdayPointsEnabled: row.querySelectorAll('input[type="checkbox"]')[3].checked
|
||||||
|
};
|
||||||
|
data.push(levelData);
|
||||||
|
});
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 将需要在HTML中调用的函数暴露到全局作用域
|
||||||
|
window.addCoupon = addCoupon;
|
||||||
|
window.saveLevelEdit = saveLevelEdit;
|
||||||
|
|
||||||
|
// 页面清理函数(可选)
|
||||||
|
function cleanupLevelEdit() {
|
||||||
|
// 清理事件监听器等
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,104 @@
|
||||||
|
/**
|
||||||
|
* 等级设置页面功能模块
|
||||||
|
* 包含多选下拉框功能
|
||||||
|
*/
|
||||||
|
|
||||||
|
// 页面初始化函数
|
||||||
|
function initLevelSettings() {
|
||||||
|
console.log('等级设置页面已初始化');
|
||||||
|
// 设置外部点击监听器
|
||||||
|
setupOutsideClickListener();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 切换下拉框显示/隐藏
|
||||||
|
function toggleDropdown() {
|
||||||
|
const options = document.getElementById('stallOptions');
|
||||||
|
const arrow = document.querySelector('.multiselect-arrow');
|
||||||
|
|
||||||
|
if (options && arrow) {
|
||||||
|
if (options.classList.contains('show')) {
|
||||||
|
options.classList.remove('show');
|
||||||
|
arrow.classList.remove('rotated');
|
||||||
|
} else {
|
||||||
|
options.classList.add('show');
|
||||||
|
arrow.classList.add('rotated');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 全选/取消全选功能
|
||||||
|
function selectAll(checkbox) {
|
||||||
|
const allCheckboxes = document.querySelectorAll('#stallOptions input[type="checkbox"]:not([value="all"])');
|
||||||
|
|
||||||
|
if (checkbox.checked) {
|
||||||
|
allCheckboxes.forEach(cb => cb.checked = true);
|
||||||
|
} else {
|
||||||
|
allCheckboxes.forEach(cb => cb.checked = false);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateSelection();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新选择状态和显示文本
|
||||||
|
function updateSelection() {
|
||||||
|
const allCheckbox = document.querySelector('input[value="all"]');
|
||||||
|
const otherCheckboxes = document.querySelectorAll('#stallOptions input[type="checkbox"]:not([value="all"])');
|
||||||
|
const selectedText = document.querySelector('.multiselect-selected');
|
||||||
|
|
||||||
|
if (!allCheckbox || !selectedText) return;
|
||||||
|
|
||||||
|
const checkedBoxes = Array.from(otherCheckboxes).filter(cb => cb.checked);
|
||||||
|
const allChecked = checkedBoxes.length === otherCheckboxes.length;
|
||||||
|
|
||||||
|
// 更新"全部"复选框状态
|
||||||
|
allCheckbox.checked = allChecked;
|
||||||
|
|
||||||
|
// 更新显示文本
|
||||||
|
if (checkedBoxes.length === 0) {
|
||||||
|
selectedText.textContent = '请选择摊位名称...';
|
||||||
|
} else if (allChecked) {
|
||||||
|
selectedText.textContent = '全部';
|
||||||
|
} else if (checkedBoxes.length === 1) {
|
||||||
|
selectedText.textContent = checkedBoxes[0].value;
|
||||||
|
} else {
|
||||||
|
selectedText.textContent = `已选择${checkedBoxes.length}个摊位`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 点击外部关闭下拉框的事件监听器
|
||||||
|
function setupOutsideClickListener() {
|
||||||
|
document.addEventListener('click', function(event) {
|
||||||
|
const container = document.querySelector('.multiselect-container');
|
||||||
|
if (container && !container.contains(event.target)) {
|
||||||
|
const options = document.getElementById('stallOptions');
|
||||||
|
const arrow = document.querySelector('.multiselect-arrow');
|
||||||
|
if (options && arrow) {
|
||||||
|
options.classList.remove('show');
|
||||||
|
arrow.classList.remove('rotated');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 页面清理函数(当页面被关闭时调用)
|
||||||
|
function cleanupLevelSettings() {
|
||||||
|
// 移除事件监听器等清理工作
|
||||||
|
console.log('等级设置页面已清理');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 打开等级明细页面
|
||||||
|
function openLevelDetails(merchantName) {
|
||||||
|
// 打开新的tab页面显示该商户的等级明细
|
||||||
|
const tabTitle = `${merchantName} - 等级设置明细`;
|
||||||
|
if (typeof window.openTab === 'function') {
|
||||||
|
window.openTab(tabTitle, 'level-details');
|
||||||
|
} else {
|
||||||
|
console.error('openTab函数未找到');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 将函数暴露到全局作用域,以便HTML中的onclick可以调用
|
||||||
|
window.toggleDropdown = toggleDropdown;
|
||||||
|
window.selectAll = selectAll;
|
||||||
|
window.updateSelection = updateSelection;
|
||||||
|
window.openLevelDetails = openLevelDetails;
|
||||||
|
|
@ -0,0 +1,101 @@
|
||||||
|
<div class="page-content">
|
||||||
|
<div class="page-header">
|
||||||
|
<h2 id="merchantName">时尚服装店</h2>
|
||||||
|
<span class="page-subtitle">- 等级设置明细</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 操作按钮区域 -->
|
||||||
|
<div class="action-section">
|
||||||
|
<button class="btn btn-primary" onclick="addLevel()">等级编辑</button>
|
||||||
|
<button class="btn" onclick="saveLevelSettings()">提交</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 等级明细表格 -->
|
||||||
|
<table class="table level-details-table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>等级名称</th>
|
||||||
|
<th>所需成长值</th>
|
||||||
|
<th>会员人数</th>
|
||||||
|
<th>会员权益</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody id="levelDetailsBody">
|
||||||
|
<tr>
|
||||||
|
<td>LV1</td>
|
||||||
|
<td>100</td>
|
||||||
|
<td>1250</td>
|
||||||
|
<td>9.5折优惠</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>LV2</td>
|
||||||
|
<td>500</td>
|
||||||
|
<td>850</td>
|
||||||
|
<td>9折优惠, 积分双倍</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>LV3</td>
|
||||||
|
<td>1200</td>
|
||||||
|
<td>450</td>
|
||||||
|
<td>8.5折优惠, 积分双倍, 生日优惠券</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>LV4</td>
|
||||||
|
<td>2500</td>
|
||||||
|
<td>180</td>
|
||||||
|
<td>8折优惠, 积分三倍, 生日优惠券, 专属客服</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.page-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: baseline;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-header h2 {
|
||||||
|
margin: 0;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-subtitle {
|
||||||
|
color: #666;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-section {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-section .btn {
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.level-details-table {
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.level-details-table th,
|
||||||
|
.level-details-table td {
|
||||||
|
text-align: center;
|
||||||
|
padding: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.level-details-table th {
|
||||||
|
background-color: #f8f9fa;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.level-details-table tr:nth-child(even) {
|
||||||
|
background-color: #f8f9fa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.level-details-table tr:hover {
|
||||||
|
background-color: #e8f4f8;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,328 @@
|
||||||
|
<div class="page-content">
|
||||||
|
<div class="page-header">
|
||||||
|
<h2 id="merchantName">时尚服装店</h2>
|
||||||
|
<span class="page-subtitle">- 等级编辑</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 操作按钮区域 -->
|
||||||
|
<div class="action-section">
|
||||||
|
<button class="btn btn-primary" onclick="saveLevelEdit()">提交</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 等级编辑表格 -->
|
||||||
|
<table class="table level-edit-table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>等级</th>
|
||||||
|
<th>等级名称</th>
|
||||||
|
<th>成长值范围</th>
|
||||||
|
<th>开启会员折扣</th>
|
||||||
|
<th>折扣率(%)</th>
|
||||||
|
<th>开启积分兑换</th>
|
||||||
|
<th>开启生日优惠券</th>
|
||||||
|
<th>生日优惠券操作</th>
|
||||||
|
<th>开启生日双倍积分</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody id="levelEditBody">
|
||||||
|
<tr>
|
||||||
|
<td>LV1</td>
|
||||||
|
<td>
|
||||||
|
<input type="text" value="铜牌会员" class="form-input">
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div class="range-input">
|
||||||
|
<input type="number" value="0" class="form-input range-start"> -
|
||||||
|
<input type="number" value="100" class="form-input range-end">
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<label class="switch">
|
||||||
|
<input type="checkbox" checked>
|
||||||
|
<span class="slider"></span>
|
||||||
|
</label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input type="number" value="5" class="form-input discount-input">
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<label class="switch">
|
||||||
|
<input type="checkbox">
|
||||||
|
<span class="slider"></span>
|
||||||
|
</label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<label class="switch">
|
||||||
|
<input type="checkbox">
|
||||||
|
<span class="slider"></span>
|
||||||
|
</label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<button class="btn btn-action" onclick="addCoupon('LV1')">添加优惠券</button>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<label class="switch">
|
||||||
|
<input type="checkbox">
|
||||||
|
<span class="slider"></span>
|
||||||
|
</label>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>LV2</td>
|
||||||
|
<td>
|
||||||
|
<input type="text" value="银牌会员" class="form-input">
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div class="range-input">
|
||||||
|
<input type="number" value="101" class="form-input range-start"> -
|
||||||
|
<input type="number" value="500" class="form-input range-end">
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<label class="switch">
|
||||||
|
<input type="checkbox" checked>
|
||||||
|
<span class="slider"></span>
|
||||||
|
</label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input type="number" value="10" class="form-input discount-input">
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<label class="switch">
|
||||||
|
<input type="checkbox" checked>
|
||||||
|
<span class="slider"></span>
|
||||||
|
</label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<label class="switch">
|
||||||
|
<input type="checkbox" checked>
|
||||||
|
<span class="slider"></span>
|
||||||
|
</label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<button class="btn btn-action" onclick="addCoupon('LV2')">添加优惠券</button>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<label class="switch">
|
||||||
|
<input type="checkbox" checked>
|
||||||
|
<span class="slider"></span>
|
||||||
|
</label>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>LV3</td>
|
||||||
|
<td>
|
||||||
|
<input type="text" value="金牌会员" class="form-input">
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div class="range-input">
|
||||||
|
<input type="number" value="501" class="form-input range-start"> -
|
||||||
|
<input type="number" value="1200" class="form-input range-end">
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<label class="switch">
|
||||||
|
<input type="checkbox" checked>
|
||||||
|
<span class="slider"></span>
|
||||||
|
</label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input type="number" value="15" class="form-input discount-input">
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<label class="switch">
|
||||||
|
<input type="checkbox" checked>
|
||||||
|
<span class="slider"></span>
|
||||||
|
</label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<label class="switch">
|
||||||
|
<input type="checkbox" checked>
|
||||||
|
<span class="slider"></span>
|
||||||
|
</label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<button class="btn btn-action" onclick="addCoupon('LV3')">添加优惠券</button>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<label class="switch">
|
||||||
|
<input type="checkbox" checked>
|
||||||
|
<span class="slider"></span>
|
||||||
|
</label>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>LV4</td>
|
||||||
|
<td>
|
||||||
|
<input type="text" value="钻石会员" class="form-input">
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div class="range-input">
|
||||||
|
<input type="number" value="1201" class="form-input range-start"> -
|
||||||
|
<input type="number" value="9999" class="form-input range-end">
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<label class="switch">
|
||||||
|
<input type="checkbox" checked>
|
||||||
|
<span class="slider"></span>
|
||||||
|
</label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input type="number" value="20" class="form-input discount-input">
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<label class="switch">
|
||||||
|
<input type="checkbox" checked>
|
||||||
|
<span class="slider"></span>
|
||||||
|
</label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<label class="switch">
|
||||||
|
<input type="checkbox" checked>
|
||||||
|
<span class="slider"></span>
|
||||||
|
</label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<button class="btn btn-action" onclick="addCoupon('LV4')">添加优惠券</button>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<label class="switch">
|
||||||
|
<input type="checkbox" checked>
|
||||||
|
<span class="slider"></span>
|
||||||
|
</label>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.page-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: baseline;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-header h2 {
|
||||||
|
margin: 0;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-subtitle {
|
||||||
|
color: #666;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-section {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-section .btn {
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.level-edit-table {
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 20px;
|
||||||
|
table-layout: fixed;
|
||||||
|
}
|
||||||
|
|
||||||
|
.level-edit-table th,
|
||||||
|
.level-edit-table td {
|
||||||
|
text-align: center;
|
||||||
|
padding: 12px 8px;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.level-edit-table th {
|
||||||
|
background-color: #f8f9fa;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.level-edit-table tr:nth-child(even) {
|
||||||
|
background-color: #f8f9fa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.level-edit-table tr:hover {
|
||||||
|
background-color: #e8f4f8;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 表单输入框样式 */
|
||||||
|
.form-input {
|
||||||
|
width: 100%;
|
||||||
|
padding: 6px 8px;
|
||||||
|
border: 1px solid #bdc3c7;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 12px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 范围输入框样式 */
|
||||||
|
.range-input {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 5px;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.range-start, .range-end {
|
||||||
|
width: 60px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.discount-input {
|
||||||
|
width: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 开关按钮调整 */
|
||||||
|
.level-edit-table .switch {
|
||||||
|
width: 40px;
|
||||||
|
height: 20px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.level-edit-table .slider {
|
||||||
|
border-radius: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.level-edit-table .slider:before {
|
||||||
|
height: 14px;
|
||||||
|
width: 14px;
|
||||||
|
left: 3px;
|
||||||
|
bottom: 3px;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.level-edit-table input:checked + .slider:before {
|
||||||
|
transform: translateX(20px);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 操作按钮样式 */
|
||||||
|
.btn-action {
|
||||||
|
background-color: #3498db;
|
||||||
|
color: white;
|
||||||
|
font-size: 12px;
|
||||||
|
padding: 4px 8px;
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-action:hover {
|
||||||
|
background-color: #2980b9;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 表格列宽调整 */
|
||||||
|
.level-edit-table th:nth-child(1) { width: 60px; } /* 等级 */
|
||||||
|
.level-edit-table th:nth-child(2) { width: 100px; } /* 等级名称 */
|
||||||
|
.level-edit-table th:nth-child(3) { width: 120px; } /* 成长值范围 */
|
||||||
|
.level-edit-table th:nth-child(4) { width: 80px; } /* 开启会员折扣 */
|
||||||
|
.level-edit-table th:nth-child(5) { width: 80px; } /* 折扣率 */
|
||||||
|
.level-edit-table th:nth-child(6) { width: 80px; } /* 开启积分兑换 */
|
||||||
|
.level-edit-table th:nth-child(7) { width: 80px; } /* 开启生日优惠券 */
|
||||||
|
.level-edit-table th:nth-child(8) { width: 100px; } /* 生日优惠券操作 */
|
||||||
|
.level-edit-table th:nth-child(9) { width: 80px; } /* 开启生日双倍积分 */
|
||||||
|
</style>
|
||||||
|
|
@ -1,57 +1,189 @@
|
||||||
<div class="page-content">
|
<div class="page-content">
|
||||||
<h2>等级设置</h2>
|
<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">
|
<!-- 搜索区域 -->
|
||||||
|
<div class="search-section">
|
||||||
|
<div class="form-group">
|
||||||
|
<label>摊位名称</label>
|
||||||
|
<div class="multiselect-container">
|
||||||
|
<div class="multiselect-dropdown" onclick="toggleDropdown()">
|
||||||
|
<span class="multiselect-selected">请选择摊位名称...</span>
|
||||||
|
<span class="multiselect-arrow">▼</span>
|
||||||
|
</div>
|
||||||
|
<div class="multiselect-options" id="stallOptions">
|
||||||
|
<label class="multiselect-option">
|
||||||
|
<input type="checkbox" value="all" onchange="selectAll(this)">
|
||||||
|
<span>全部</span>
|
||||||
|
</label>
|
||||||
|
<label class="multiselect-option">
|
||||||
|
<input type="checkbox" value="牛牛蔬菜店" onchange="updateSelection()">
|
||||||
|
<span>牛牛蔬菜店</span>
|
||||||
|
</label>
|
||||||
|
<label class="multiselect-option">
|
||||||
|
<input type="checkbox" value="羊羊水果店" onchange="updateSelection()">
|
||||||
|
<span>羊羊水果店</span>
|
||||||
|
</label>
|
||||||
|
<label class="multiselect-option">
|
||||||
|
<input type="checkbox" value="小狗羊肉" onchange="updateSelection()">
|
||||||
|
<span>小狗羊肉</span>
|
||||||
|
</label>
|
||||||
|
<label class="multiselect-option">
|
||||||
|
<input type="checkbox" value="小马猪蹄" onchange="updateSelection()">
|
||||||
|
<span>小马猪蹄</span>
|
||||||
|
</label>
|
||||||
|
<label class="multiselect-option">
|
||||||
|
<input type="checkbox" value="小鱼生鲜" onchange="updateSelection()">
|
||||||
|
<span>小鱼生鲜</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<button class="btn btn-search">查询</button>
|
||||||
|
<button class="btn btn-primary">批量会员等级编辑</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 商户列表表格 -->
|
||||||
|
<table class="table merchant-table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>等级名称</th>
|
<th>摊位名称</th>
|
||||||
<th>积分要求</th>
|
<th>是否启用会员</th>
|
||||||
<th>会员数量</th>
|
<th>会员等级</th>
|
||||||
<th>操作</th>
|
<th>操作</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td>普通会员</td>
|
<td>牛牛蔬菜店</td>
|
||||||
<td>0</td>
|
|
||||||
<td>1,234</td>
|
|
||||||
<td>
|
<td>
|
||||||
<button class="btn">编辑</button>
|
<label class="switch">
|
||||||
<button class="btn">删除</button>
|
<input type="checkbox" checked>
|
||||||
|
<span class="slider"></span>
|
||||||
|
</label>
|
||||||
|
</td>
|
||||||
|
<td>lv1, lv2, lv3, lv4</td>
|
||||||
|
<td>
|
||||||
|
<button class="btn-link" onclick="openLevelDetails('牛牛蔬菜店')">设置等级明细</button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>银牌会员</td>
|
<td>羊羊水果店</td>
|
||||||
<td>1,000</td>
|
|
||||||
<td>567</td>
|
|
||||||
<td>
|
<td>
|
||||||
<button class="btn">编辑</button>
|
<label class="switch">
|
||||||
<button class="btn">删除</button>
|
<input type="checkbox">
|
||||||
|
<span class="slider"></span>
|
||||||
|
</label>
|
||||||
|
</td>
|
||||||
|
<td>lv1, lv2, lv3</td>
|
||||||
|
<td>
|
||||||
|
<button class="btn-link" onclick="openLevelDetails('羊羊水果店')">设置等级明细</button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>金牌会员</td>
|
<td>小狗羊肉</td>
|
||||||
<td>5,000</td>
|
|
||||||
<td>123</td>
|
|
||||||
<td>
|
<td>
|
||||||
<button class="btn">编辑</button>
|
<label class="switch">
|
||||||
<button class="btn">删除</button>
|
<input type="checkbox" checked>
|
||||||
|
<span class="slider"></span>
|
||||||
|
</label>
|
||||||
|
</td>
|
||||||
|
<td>lv1, lv2, lv3, lv4</td>
|
||||||
|
<td>
|
||||||
|
<button class="btn-link" onclick="openLevelDetails('小狗羊肉')">设置等级明细</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>小马猪蹄</td>
|
||||||
|
<td>
|
||||||
|
<label class="switch">
|
||||||
|
<input type="checkbox">
|
||||||
|
<span class="slider"></span>
|
||||||
|
</label>
|
||||||
|
</td>
|
||||||
|
<td>lv1, lv2</td>
|
||||||
|
<td>
|
||||||
|
<button class="btn-link" onclick="openLevelDetails('小马猪蹄')">设置等级明细</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>小鱼生鲜</td>
|
||||||
|
<td>
|
||||||
|
<label class="switch">
|
||||||
|
<input type="checkbox" checked>
|
||||||
|
<span class="slider"></span>
|
||||||
|
</label>
|
||||||
|
</td>
|
||||||
|
<td>lv1, lv2, lv3, lv4</td>
|
||||||
|
<td>
|
||||||
|
<button class="btn-link" onclick="openLevelDetails('小鱼生鲜')">设置等级明细</button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.multiselect-container {
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
min-width: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.multiselect-dropdown {
|
||||||
|
border: 1px solid #bdc3c7;
|
||||||
|
padding: 8px 12px;
|
||||||
|
background: white;
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.multiselect-dropdown:hover {
|
||||||
|
border-color: #3498db;
|
||||||
|
}
|
||||||
|
|
||||||
|
.multiselect-arrow {
|
||||||
|
transition: transform 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.multiselect-arrow.rotated {
|
||||||
|
transform: rotate(180deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.multiselect-options {
|
||||||
|
position: absolute;
|
||||||
|
top: 100%;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
background: white;
|
||||||
|
border: 1px solid #bdc3c7;
|
||||||
|
border-top: none;
|
||||||
|
max-height: 200px;
|
||||||
|
overflow-y: auto;
|
||||||
|
z-index: 1000;
|
||||||
|
display: none;
|
||||||
|
border-radius: 0 0 4px 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.multiselect-options.show {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.multiselect-option {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 8px 12px;
|
||||||
|
cursor: pointer;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.multiselect-option:hover {
|
||||||
|
background-color: #f8f9fa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.multiselect-option input[type="checkbox"] {
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -160,6 +160,9 @@ function closeTab(tabId) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 存储已加载的页面脚本,避免重复加载
|
||||||
|
const loadedPageScripts = new Set();
|
||||||
|
|
||||||
// 动态加载页面内容
|
// 动态加载页面内容
|
||||||
async function loadPageContent(contentType) {
|
async function loadPageContent(contentType) {
|
||||||
try {
|
try {
|
||||||
|
|
@ -168,6 +171,10 @@ async function loadPageContent(contentType) {
|
||||||
throw new Error(`HTTP error! status: ${response.status}`);
|
throw new Error(`HTTP error! status: ${response.status}`);
|
||||||
}
|
}
|
||||||
const content = await response.text();
|
const content = await response.text();
|
||||||
|
|
||||||
|
// 页面内容加载完成后,尝试加载对应的JavaScript文件
|
||||||
|
await loadPageScript(contentType);
|
||||||
|
|
||||||
return content;
|
return content;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('加载页面失败:', error);
|
console.error('加载页面失败:', error);
|
||||||
|
|
@ -181,6 +188,58 @@ async function loadPageContent(contentType) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 动态加载页面对应的JavaScript文件
|
||||||
|
async function loadPageScript(contentType) {
|
||||||
|
const scriptPath = `js/${contentType}.js`;
|
||||||
|
|
||||||
|
// 如果已经加载过该脚本,直接返回
|
||||||
|
if (loadedPageScripts.has(scriptPath)) {
|
||||||
|
// 调用页面初始化函数(如果存在)
|
||||||
|
const initFunctionName = `init${toCamelCase(contentType)}`;
|
||||||
|
if (typeof window[initFunctionName] === 'function') {
|
||||||
|
window[initFunctionName]();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 检查文件是否存在
|
||||||
|
const checkResponse = await fetch(scriptPath, { method: 'HEAD' });
|
||||||
|
if (!checkResponse.ok) {
|
||||||
|
console.log(`页面脚本文件不存在: ${scriptPath}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 动态创建script标签加载JavaScript文件
|
||||||
|
const script = document.createElement('script');
|
||||||
|
script.src = scriptPath;
|
||||||
|
script.onload = () => {
|
||||||
|
console.log(`页面脚本已加载: ${scriptPath}`);
|
||||||
|
loadedPageScripts.add(scriptPath);
|
||||||
|
|
||||||
|
// 调用页面初始化函数(如果存在)
|
||||||
|
const initFunctionName = `init${toCamelCase(contentType)}`;
|
||||||
|
if (typeof window[initFunctionName] === 'function') {
|
||||||
|
window[initFunctionName]();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
script.onerror = () => {
|
||||||
|
console.error(`页面脚本加载失败: ${scriptPath}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
document.head.appendChild(script);
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('检查页面脚本文件时出错:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 将kebab-case转换为CamelCase
|
||||||
|
function toCamelCase(str) {
|
||||||
|
return str.replace(/-([a-z])/g, (match, letter) => letter.toUpperCase())
|
||||||
|
.replace(/^[a-z]/, match => match.toUpperCase());
|
||||||
|
}
|
||||||
|
|
||||||
// 键盘快捷键支持
|
// 键盘快捷键支持
|
||||||
document.addEventListener('keydown', function(e) {
|
document.addEventListener('keydown', function(e) {
|
||||||
// ESC键关闭当前tab(除了首页)
|
// ESC键关闭当前tab(除了首页)
|
||||||
|
|
|
||||||
|
|
@ -174,7 +174,7 @@ body {
|
||||||
|
|
||||||
/* 页面内容样式 */
|
/* 页面内容样式 */
|
||||||
.page-content {
|
.page-content {
|
||||||
max-width: 800px;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.page-content h2 {
|
.page-content h2 {
|
||||||
|
|
@ -241,3 +241,104 @@ body {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
color: #2c3e50;
|
color: #2c3e50;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 搜索区域样式 */
|
||||||
|
.search-section {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
padding: 15px;
|
||||||
|
background-color: #f8f9fa;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-section .form-group {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-section label {
|
||||||
|
min-width: 80px;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-input {
|
||||||
|
flex: 1;
|
||||||
|
max-width: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-search {
|
||||||
|
background-color: #27ae60;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-search:hover {
|
||||||
|
background-color: #219a52;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 开关按钮样式 */
|
||||||
|
.switch {
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
width: 50px;
|
||||||
|
height: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.switch input {
|
||||||
|
opacity: 0;
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slider {
|
||||||
|
position: absolute;
|
||||||
|
cursor: pointer;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background-color: #ccc;
|
||||||
|
border-radius: 24px;
|
||||||
|
transition: .4s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slider:before {
|
||||||
|
position: absolute;
|
||||||
|
content: "";
|
||||||
|
height: 18px;
|
||||||
|
width: 18px;
|
||||||
|
left: 3px;
|
||||||
|
bottom: 3px;
|
||||||
|
background-color: white;
|
||||||
|
border-radius: 50%;
|
||||||
|
transition: .4s;
|
||||||
|
}
|
||||||
|
|
||||||
|
input:checked + .slider {
|
||||||
|
background-color: #27ae60;
|
||||||
|
}
|
||||||
|
|
||||||
|
input:checked + .slider:before {
|
||||||
|
transform: translateX(26px);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 链接按钮样式 */
|
||||||
|
.btn-link {
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
color: #27ae60;
|
||||||
|
cursor: pointer;
|
||||||
|
text-decoration: none;
|
||||||
|
font-size: 14px;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-link:hover {
|
||||||
|
color: #219a52;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 商户表格特殊样式 */
|
||||||
|
.merchant-table td {
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue