commit 9a07a81e9702db782097f2d2ebaaf0eabedf3d4f Author: linbin <495561397@qq.com> Date: Thu Jul 31 09:20:15 2025 +0800 1 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f650315 --- /dev/null +++ b/.gitignore @@ -0,0 +1,27 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules + +# next.js +/.next/ +/out/ + +# production +/build + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.pnpm-debug.log* + +# env files +.env* + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts \ No newline at end of file diff --git a/merchant/CLAUDE.md b/merchant/CLAUDE.md new file mode 100644 index 0000000..8ad834f --- /dev/null +++ b/merchant/CLAUDE.md @@ -0,0 +1,91 @@ +# 大数集市商户端 - DEMO项目文档 + +## 🚨 重要实现约束(大模型必读) + +### DEMO项目核心原则 +1. **这是一个纯展示性DEMO项目** - 只需要实现UI展示和基础交互效果,无需真实数据处理 +2. **占位功能实现原则** - 所有功能只需要实现交互效果和UI反馈,不需要实现真实的数据联动和业务逻辑 +3. **视觉完整性优先** - 重点在于元素摆放位置准确、交互反馈完整,不强调样式美观性 +4. **前端纯静态实现** - 使用原生JavaScript实现,无后端交互,无真实数据存储 + +### 功能实现约束 +- **筛选功能**: 只需要实现UI交互(下拉框、选择、按钮点击),筛选结果可以是模拟的视觉反馈 +- **表单提交**: 只需要显示成功提示,无需真实提交数据 +- **数据展示**: 使用硬编码的模拟数据,无需动态数据加载 +- **状态管理**: 只需要维护页面内的UI状态,无需持久化存储 + +### 技术实现要求 +- 使用原生HTML/CSS/JavaScript,无外部框架依赖 +- 实现Tab系统的完整交互体验 +- 保持代码清晰简洁,便于理解和演示 +- 确保所有UI元素位置准确,符合设计要求 + +--- + +## 项目概述 +**这是一个DEMO项目,主要用于展示页面元素布局和交互功能,不强调样式美观性,重点在于元素摆放位置的准确性和功能完整性。** + +这是一个中文商户后台管理系统的演示项目,采用了现代化的前端设计和Tab标签页架构。项目采用左中布局,左侧固定侧边栏,中央区域使用Tab系统展示会员管理功能。 + +## 项目架构说明 + +### 文件结构 (2025-07-30 最新更新) +``` +chinese-merchant-dashboard/ +├── index.html # 主页面(导航入口) +├── css/ +│ └── styles.css # 全局样式文件(包含Tab样式) +├── js/ +│ ├── main.js # 主页面逻辑(简化版) +│ ├── common.js # 通用工具函数和组件 +│ ├── sidebar.js # 侧边栏通用逻辑 +│ ├── member-tabs.js # 会员管理Tab系统核心逻辑 +│ └── pages/ # 页面专用JS文件目录 +│ ├── level-settings.js # 等级设置Tab页面逻辑 +│ ├── data-center.js # 数据中心页面逻辑 +│ └── coupon-marketing.js # 优惠券营销页面逻辑 +└── pages/ + ├── data-center.html # 数据中心页面 + ├── coupon-marketing.html # 优惠券营销工具管理页面 + └── member/ # 会员管理模块 + ├── level-settings.html # 等级设置页面(Tab容器) + ├── level-detail.html # 等级详情页面(已弃用) + └── level-edit.html # 等级编辑页面(已弃用) +``` + +### 设计原则 +1. **功能展示优先**: 重点展示功能完整性而非视觉效果 +2. **元素位置准确**: 严格按照需求放置UI元素 +3. **Tab系统架构**: 会员管理采用Tab标签页,提升用户体验 +4. **演示友好**: 便于展示不同功能模块的交互效果 + +## 实现约束追加说明 + +### 项目实验性约束 +- **演示优先原则**: 所有功能仅作为交互和UI展示的占位实现 +- **极简主义设计**: 代码和功能追求最小必要实现 +- **可视化交互重点**: 重点关注用户交互流程和界面响应 +- **模拟数据填充**: 所有数据均为硬编码模拟数据,无真实业务逻辑 + +### 代码与功能约束 +- 所有JS交互仅模拟实际效果,不涉及真实数据处理 +- 表单提交、筛选功能均为本地模拟交互 +- 开关、弹窗等组件仅展示交互流程 +- 代码保持高可读性和最小依赖原则 + +### 功能模拟策略 +- UI交互全部通过JavaScript模拟实现 +- 数据展示使用静态、可预测的模拟数据 +- 表单验证仅展示交互流程,不进行实质性数据校验 +- 状态管理仅维持页面内临时状态 + +### 技术限制 +- 严格使用原生Web技术栈 +- 禁止引入任何外部框架和类库 +- 代码实现追求极简和直观 +- 所有功能通过原生JavaScript实现用户交互 + +--- +*文档更新时间: 2025-07-30* +*项目状态: 完成DEMO项目实现约束补充说明* +*最新特性: 详细阐述项目的实验性约束和功能模拟策略* \ No newline at end of file diff --git a/merchant/README.md b/merchant/README.md new file mode 100644 index 0000000..01cd2b0 --- /dev/null +++ b/merchant/README.md @@ -0,0 +1,116 @@ +# 大数集市商户端 Demo + +这是一个纯HTML版本的中文商户后台管理系统演示项目,基于原始的Next.js项目转换而来。 + +## 项目结构 + +``` +demo/ +├── index.html # 主页面文件 +├── css/ +│ └── styles.css # 样式文件 +├── js/ +│ └── main.js # JavaScript交互逻辑 +├── images/ # 静态资源文件 +│ ├── placeholder.svg +│ ├── placeholder.png +│ └── ... +└── README.md # 说明文档 +``` + +## 功能特性 + +### ✅ 已实现功能 + +1. **完整的页面布局** + - 绿色主题的顶部导航栏 + - 左侧折叠式菜单 + - 右侧主内容区域 + +2. **交互功能** + - 菜单展开/收起动画 + - 页面内容切换(如等级设置页面) + - 开关按钮的切换效果 + - 搜索菜单功能 + +3. **响应式设计** + - 支持桌面端和移动端布局 + - 自适应屏幕大小 + +4. **用户体验** + - 平滑的动画过渡效果 + - 键盘快捷键支持(ESC回首页,Ctrl+F搜索) + - 通知提示系统 + +### 🎯 主要页面 + +- **首页**: 默认欢迎页面 +- **等级设置**: 会员等级管理表格,包含开关切换功能 + +### 🔧 菜单项 + +- 首页 +- 运营管理(可展开) +- 数据中心 +- 优惠券营销工具管理 +- 预售营销工具管理 +- 会员管理(可展开,包含等级设置等子菜单) +- 钱包管理(可展开) +- 运费管理(可展开) + +## 使用方法 + +1. **直接打开** + ```bash + # 在浏览器中打开 + open index.html + # 或者 + double-click index.html + ``` + +2. **本地服务器运行**(推荐) + ```bash + # 使用Python + python -m http.server 8000 + # 或使用Node.js + npx serve . + # 然后访问 http://localhost:8000 + ``` + +## 技术实现 + +- **HTML5**: 语义化标签结构 +- **CSS3**: 基于Tailwind CSS的样式系统,包含自定义动画 +- **JavaScript ES6+**: 原生JS实现所有交互功能 +- **响应式设计**: 适配不同设备屏幕 + +## 浏览器兼容性 + +- Chrome 60+ +- Firefox 55+ +- Safari 12+ +- Edge 79+ + +## 快捷键 + +- `ESC`: 返回首页 +- `Ctrl+F`: 聚焦搜索框 + +## 定制说明 + +如需修改样式或功能,可以编辑以下文件: +- `css/styles.css`: 修改样式 +- `js/main.js`: 修改交互逻辑 +- `index.html`: 修改页面结构 + +## 注意事项 + +1. 这是一个静态演示版本,所有数据都是模拟数据 +2. 开关切换、按钮点击等操作只有视觉反馈,不会实际提交数据 +3. 为了演示效果,保留了完整的交互逻辑和动画效果 + +## 原项目信息 + +- 原技术栈: Next.js + React + Tailwind CSS + shadcn/ui +- 转换时间: 2025年 +- 转换方式: 手动转换为纯HTML/CSS/JS \ No newline at end of file diff --git a/merchant/css/styles.css b/merchant/css/styles.css new file mode 100644 index 0000000..8054eb1 --- /dev/null +++ b/merchant/css/styles.css @@ -0,0 +1,1073 @@ +/* Reset and Base Styles */ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; + line-height: 1.5; + color: #111827; + background-color: #f9fafb; +} + +/* Utility Classes */ +.min-h-screen { + min-height: 100vh; +} + +.bg-gray-50 { + background-color: #f9fafb; +} + +.bg-green-700 { + background-color: #15803d; +} + +.bg-green-600 { + background-color: #16a34a; +} + +.bg-white { + background-color: #ffffff; +} + +.bg-gray-100 { + background-color: #f3f4f6; +} + +.bg-gray-200 { + background-color: #e5e7eb; +} + +.bg-gray-300 { + background-color: #d1d5db; +} + +.text-white { + color: #ffffff; +} + +.text-gray-500 { + color: #6b7280; +} + +.text-gray-600 { + color: #4b5563; +} + +.text-gray-700 { + color: #374151; +} + +.text-gray-900 { + color: #111827; +} + +.text-blue-500 { + color: #3b82f6; +} + +.text-green-600 { + color: #16a34a; +} + +.text-green-900 { + color: #14532d; +} + +.px-4 { + padding-left: 1rem; + padding-right: 1rem; +} + +.py-3 { + padding-top: 0.75rem; + padding-bottom: 0.75rem; +} + +.py-2 { + padding-top: 0.5rem; + padding-bottom: 0.5rem; +} + +.py-2\.5 { + padding-top: 0.625rem; + padding-bottom: 0.625rem; +} + +.py-4 { + padding-top: 1rem; + padding-bottom: 1rem; +} + +.py-6 { + padding-top: 1.5rem; + padding-bottom: 1.5rem; +} + +.px-3 { + padding-left: 0.75rem; + padding-right: 0.75rem; +} + +.px-6 { + padding-left: 1.5rem; + padding-right: 1.5rem; +} + +.p-2 { + padding: 0.5rem; +} + +.p-3 { + padding: 0.75rem; +} + +.p-6 { + padding: 1.5rem; +} + +.flex { + display: flex; +} + +.items-center { + align-items: center; +} + +.justify-between { + justify-content: space-between; +} + +.justify-center { + justify-content: center; +} + +.gap-2 { + gap: 0.5rem; +} + +.gap-3 { + gap: 0.75rem; +} + +.gap-4 { + gap: 1rem; +} + +.text-lg { + font-size: 1.125rem; + line-height: 1.75rem; +} + +.text-sm { + font-size: 0.875rem; + line-height: 1.25rem; +} + +.text-xs { + font-size: 0.75rem; + line-height: 1rem; +} + +.font-medium { + font-weight: 500; +} + +.h-4 { + height: 1rem; +} + +.w-4 { + width: 1rem; +} + +.h-3 { + height: 0.75rem; +} + +.w-3 { + width: 0.75rem; +} + +.h-8 { + height: 2rem; +} + +.w-8 { + width: 2rem; +} + +.h-16 { + height: 4rem; +} + +.w-9 { + width: 2.25rem; +} + +.h-4 { + height: 1rem; +} + +.w-4 { + width: 1rem; +} + +.after\:h-4::after { + height: 1rem; +} + +.after\:w-4::after { + width: 1rem; +} + +.peer-focus\:ring-2:focus ~ .peer-focus\:ring-2 { + box-shadow: 0 0 0 2px; +} + +.peer-focus\:ring-green-300:focus ~ .peer-focus\:ring-green-300 { + box-shadow: 0 0 0 2px rgba(134, 239, 172, 0.5); +} + +.w-16 { + width: 4rem; +} + +.bg-gray-100 { + background-color: #f3f4f6; +} + +.h-96 { + height: 24rem; +} + +.h-full { + height: 100%; +} + +.w-full { + width: 100%; +} + +.w-48 { + width: 12rem; +} + +.w-11 { + width: 2.75rem; +} + +.h-6 { + height: 1.5rem; +} + +.h-5 { + height: 1.25rem; +} + +.w-5 { + width: 1.25rem; +} + +.rounded-md { + border-radius: 0.375rem; +} + +.rounded-lg { + border-radius: 0.5rem; +} + +.rounded-full { + border-radius: 9999px; +} + +.border { + border-width: 1px; +} + +.border-r { + border-right-width: 1px; +} + +.border-b { + border-bottom-width: 1px; +} + +.border-l-2 { + border-left-width: 2px; +} + +.border-gray-200 { + border-color: #e5e7eb; +} + +.border-gray-100 { + border-color: #f3f4f6; +} + +.border-gray-300 { + border-color: #d1d5db; +} + +.border-green-500 { + border-color: #22c55e; +} + +.shadow-sm { + box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05); +} + +.cursor-pointer { + cursor: pointer; +} + +.select-none { + user-select: none; +} + +.space-y-1 > * + * { + margin-top: 0.25rem; +} + +.flex-1 { + flex: 1 1 0%; +} + +.transition-transform { + transition-property: transform; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; +} + +.transition-colors { + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; +} + +.rotate-180 { + transform: rotate(180deg); +} + +.ml-4 { + margin-left: 1rem; +} + +.mt-2 { + margin-top: 0.5rem; +} + +.mb-4 { + margin-bottom: 1rem; +} + +.mx-auto { + margin-left: auto; + margin-right: auto; +} + +.text-center { + text-align: center; +} + +.text-left { + text-align: left; +} + +.uppercase { + text-transform: uppercase; +} + +.tracking-wider { + letter-spacing: 0.05em; +} + +.whitespace-nowrap { + white-space: nowrap; +} + +.overflow-x-auto { + overflow-x: auto; +} + +.divide-y > * + * { + border-top-width: 1px; +} + +.divide-gray-200 > * + * { + border-color: #e5e7eb; +} + +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border: 0; +} + +.peer:checked ~ .peer-checked\:bg-green-600 { + background-color: #16a34a; +} + +.peer-checked\:after\:translate-x-full { + content: ''; +} + +.peer:checked ~ .peer-checked\:after\:translate-x-full::after { + transform: translateX(100%); +} + +.peer-checked\:after\:border-white::after { + border-color: #ffffff; +} + +.after\:content-\[\'\'\]::after { + content: ''; +} + +.after\:absolute::after { + position: absolute; +} + +.after\:top-\[2px\]::after { + top: 2px; +} + +.after\:left-\[2px\]::after { + left: 2px; +} + +.after\:bg-white::after { + background-color: #ffffff; +} + +.after\:border-gray-300::after { + border-color: #d1d5db; +} + +.after\:border::after { + border-width: 1px; +} + +.after\:rounded-full::after { + border-radius: 9999px; +} + +.after\:h-5::after { + height: 1.25rem; +} + +.after\:w-5::after { + width: 1.25rem; +} + +.after\:transition-all::after { + transition-property: all; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; +} + +.peer-focus\:outline-none:focus ~ .peer-focus\:outline-none { + outline: 2px solid transparent; + outline-offset: 2px; +} + +.peer-focus\:ring-4:focus ~ .peer-focus\:ring-4 { + box-shadow: 0 0 0 4px; +} + +.peer-focus\:ring-green-300:focus ~ .peer-focus\:ring-green-300 { + box-shadow: 0 0 0 4px rgba(134, 239, 172, 0.5); +} + +.min-h-\[calc\(100vh-60px\)\] { + min-height: calc(100vh - 60px); +} + +.relative { + position: relative; +} + +.inline-flex { + display: inline-flex; +} + +.absolute { + position: absolute; +} + +.top-\[2px\] { + top: 2px; +} + +.left-\[2px\] { + left: 2px; +} + +.hidden { + display: none; +} + +/* Hover Effects */ +.hover\:bg-gray-50:hover { + background-color: #f9fafb; +} + +.hover\:bg-gray-100:hover { + background-color: #f3f4f6; +} + +.bg-red-600 { + background-color: #dc2626; +} + +.hover\:bg-red-700:hover { + background-color: #b91c1c; +} + +.hover\:bg-green-700:hover { + background-color: #15803d; +} + +.hover\:text-green-900:hover { + color: #14532d; +} + +/* Focus Effects */ +.focus\:border-green-500:focus { + border-color: #22c55e; +} + +.focus\:outline-none:focus { + outline: 2px solid transparent; + outline-offset: 2px; +} + +/* Custom Toggle Switch Styles */ +.toggle-switch { + position: relative; + display: inline-block; + width: 44px; + height: 24px; +} + +.toggle-switch input { + opacity: 0; + width: 0; + height: 0; +} + +.toggle-slider { + position: absolute; + cursor: pointer; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: #e5e7eb; + transition: .4s; + border-radius: 24px; +} + +.toggle-slider:before { + position: absolute; + content: ""; + height: 20px; + width: 20px; + left: 2px; + top: 2px; + background-color: white; + transition: .4s; + border-radius: 50%; + border: 1px solid #d1d5db; +} + +input:checked + .toggle-slider { + background-color: #16a34a; +} + +input:focus + .toggle-slider { + box-shadow: 0 0 0 4px rgba(134, 239, 172, 0.3); +} + +input:checked + .toggle-slider:before { + transform: translateX(20px); + border-color: white; +} + +/* Table Styles */ +table { + border-collapse: collapse; +} + +thead th { + background-color: #f9fafb; + font-weight: 500; + text-transform: uppercase; + letter-spacing: 0.05em; + font-size: 0.75rem; + color: #6b7280; + padding: 0.75rem 1.5rem; + text-align: left; +} + +tbody td { + padding: 1rem 1.5rem; + border-top: 1px solid #e5e7eb; + font-size: 0.875rem; +} + +tbody tr:hover { + background-color: #f9fafb; +} + +/* Button Styles */ +button { + border: none; + background: none; + cursor: pointer; + font-family: inherit; +} + +/* Input Styles */ +input[type="text"] { + border: 1px solid #e5e7eb; + border-radius: 0.375rem; + padding: 0.5rem 0.75rem; + font-size: 0.875rem; + width: 100%; + transition: border-color 0.15s ease; +} + +input[type="text"]:focus { + outline: none; + border-color: #22c55e; +} + +/* Animation */ +@keyframes fadeIn { + from { opacity: 0; } + to { opacity: 1; } +} + +.fade-in { + animation: fadeIn 0.3s ease-in; +} + +/* 小开关样式 - 用于等级编辑页面 */ +.small-toggle input[type="checkbox"]:checked + div { + background-color: #16a34a !important; +} + +.small-toggle input[type="checkbox"]:checked + div:after { + transform: translateX(1rem) !important; + border-color: white !important; +} + +.small-toggle div { + background-color: #e5e7eb; + transition: all 0.3s ease; +} + +.small-toggle div:after { + content: ''; + position: absolute; + top: 2px; + left: 2px; + background-color: white; + border: 1px solid #d1d5db; + border-radius: 50%; + height: 1rem; + width: 1rem; + transition: all 0.3s ease; +} + +/* Tab样式 */ +.tab-item { + border-bottom: 2px solid transparent; + transition: all 0.2s ease; +} + +.tab-item:hover { + color: #374151; + background-color: #f9fafb; +} + +.tab-item.active { + border-bottom-color: #22c55e; + color: #16a34a; +} + +/* 输入框样式 */ +input[type="number"] { + border: 1px solid #d1d5db; + border-radius: 0.25rem; + padding: 0.25rem 0.5rem; + font-size: 0.875rem; + line-height: 1.25rem; + transition: border-color 0.15s ease; +} + +input[type="number"]:focus { + outline: none; + border-color: #22c55e; + box-shadow: 0 0 0 1px #22c55e; +} + +input[type="number"]:disabled { + background-color: #f3f4f6; + color: #9ca3af; + cursor: not-allowed; +} + +/* 按钮样式 */ +.btn-green { + background-color: #16a34a; + color: white; + padding: 0.5rem 1rem; + border-radius: 0.375rem; + font-size: 0.875rem; + font-weight: 500; + transition: background-color 0.15s ease; + border: none; + cursor: pointer; +} + +.btn-green:hover { + background-color: #15803d; +} + +.btn-gray { + background-color: #6b7280; + color: white; + padding: 0.5rem 1rem; + border-radius: 0.375rem; + font-size: 0.875rem; + font-weight: 500; + transition: background-color 0.15s ease; + border: none; + cursor: pointer; +} + +.btn-gray:hover { + background-color: #4b5563; +} +@media (max-width: 768px) { + .w-48 { + width: 100%; + } + + .flex { + flex-direction: column; + } + + .min-h-\[calc\(100vh-60px\)\] { + min-height: auto; + } +} + +/* 弹窗样式 */ +.fixed { + position: fixed; +} + +.inset-0 { + top: 0; + right: 0; + bottom: 0; + left: 0; +} + +.bg-black { + background-color: #000000; +} + +.bg-opacity-50 { + background-color: rgba(0, 0, 0, 0.5); +} + +.z-50 { + z-index: 50; +} + +.w-96 { + width: 24rem; +} + +.max-w-md { + max-width: 28rem; +} + +.mx-4 { + margin-left: 1rem; + margin-right: 1rem; +} + +.space-y-4 > * + * { + margin-top: 1rem; +} + +.mb-1 { + margin-bottom: 0.25rem; +} + +.ml-2 { + margin-left: 0.5rem; +} + +.border-t-0 { + border-top-width: 0; +} + +.rounded-t { + border-top-left-radius: 0.25rem; + border-top-right-radius: 0.25rem; +} + +.rounded-b { + border-bottom-left-radius: 0.25rem; + border-bottom-right-radius: 0.25rem; +} + +.text-red-500 { + color: #ef4444; +} + +.bg-blue-600 { + background-color: #2563eb; +} + +.hover\:bg-blue-700:hover { + background-color: #1d4ed8; +} + +.hover\:bg-gray-200:hover { + background-color: #e5e7eb; +} + +.text-gray-400 { + color: #9ca3af; +} + +.hover\:text-gray-600:hover { + color: #4b5563; +} + +.focus\:ring-2:focus { + box-shadow: 0 0 0 2px; +} + +.focus\:ring-green-500:focus { + box-shadow: 0 0 0 2px rgba(34, 197, 94, 0.5); +} + +.focus\:border-green-500:focus { + border-color: #22c55e; +} + +/* 弹窗动画 */ +@keyframes modalFadeIn { + from { + opacity: 0; + transform: scale(0.95); + } + to { + opacity: 1; + transform: scale(1); + } +} + +.modal-content { + animation: modalFadeIn 0.2s ease-out; +} + +/* 数字输入框调节按钮 */ +.number-adjuster { + display: flex; + flex-direction: column; +} + +.number-adjuster button { + padding: 0.25rem 0.5rem; + font-size: 0.75rem; + line-height: 1rem; + background-color: #f3f4f6; + border: 1px solid #d1d5db; + transition: background-color 0.15s ease; +} + +.number-adjuster button:hover { + background-color: #e5e7eb; +} + +.number-adjuster button:first-child { + border-top-left-radius: 0.25rem; + border-top-right-radius: 0.25rem; +} + +.number-adjuster button:last-child { + border-bottom-left-radius: 0.25rem; + border-bottom-right-radius: 0.25rem; + border-top-width: 0; +} + +/* 网格布局 */ +.grid { + display: grid; +} + +.grid-cols-1 { + grid-template-columns: repeat(1, minmax(0, 1fr)); +} + +.grid-cols-2 { + grid-template-columns: repeat(2, minmax(0, 1fr)); +} + +.grid-cols-4 { + grid-template-columns: repeat(4, minmax(0, 1fr)); +} + +@media (min-width: 768px) { + .md\:grid-cols-2 { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } + + .md\:grid-cols-4 { + grid-template-columns: repeat(4, minmax(0, 1fr)); + } +} + +/* 间距工具 */ +.space-x-2 > * + * { + margin-left: 0.5rem; +} + +.space-x-4 > * + * { + margin-left: 1rem; +} + +/* 徽章样式 */ +.bg-blue-100 { + background-color: #dbeafe; +} + +.text-blue-800 { + color: #1e40af; +} + +.bg-purple-100 { + background-color: #ede9fe; +} + +.text-purple-800 { + color: #5b21b6; +} + +.bg-blue-50 { + background-color: #eff6ff; +} + +.text-blue-600 { + color: #2563eb; +} + +.text-blue-900 { + color: #1e3a8a; +} + +.border-blue-200 { + border-color: #bfdbfe; +} + +.bg-green-50 { + background-color: #f0fdf4; +} + +.border-green-200 { + border-color: #bbf7d0; +} + +.text-green-900 { + color: #14532d; +} + +.text-2xl { + font-size: 1.5rem; + line-height: 2rem; +} + +.font-bold { + font-weight: 700; +} + +.flex-shrink-0 { + flex-shrink: 0; +} + +.rounded-full { + border-radius: 9999px; +} + +.px-2\.5 { + padding-left: 0.625rem; + padding-right: 0.625rem; +} + +.py-0\.5 { + padding-top: 0.125rem; + padding-bottom: 0.125rem; +} + +.font-mono { + font-family: ui-monospace, SFMono-Regular, "SF Mono", Consolas, "Liberation Mono", Menlo, monospace; +} + +.inline-block { + display: inline-block; +} + +.ml-1 { + margin-left: 0.25rem; +} + +.w-12 { + width: 3rem; +} + +.text-center { + text-align: center; +} + +.sm\:px-6 { + padding-left: 1.5rem; + padding-right: 1.5rem; +} + +.border-t { + border-top-width: 1px; +} + +.overflow-hidden { + overflow: hidden; +} + +.shadow-sm { + box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05); +} + +.focus\:border-green-500:focus { + border-color: #22c55e; +} + +.focus\:ring-green-500:focus { + box-shadow: 0 0 0 1px #22c55e; +} \ No newline at end of file diff --git a/merchant/demo/README.md b/merchant/demo/README.md new file mode 100644 index 0000000..01cd2b0 --- /dev/null +++ b/merchant/demo/README.md @@ -0,0 +1,116 @@ +# 大数集市商户端 Demo + +这是一个纯HTML版本的中文商户后台管理系统演示项目,基于原始的Next.js项目转换而来。 + +## 项目结构 + +``` +demo/ +├── index.html # 主页面文件 +├── css/ +│ └── styles.css # 样式文件 +├── js/ +│ └── main.js # JavaScript交互逻辑 +├── images/ # 静态资源文件 +│ ├── placeholder.svg +│ ├── placeholder.png +│ └── ... +└── README.md # 说明文档 +``` + +## 功能特性 + +### ✅ 已实现功能 + +1. **完整的页面布局** + - 绿色主题的顶部导航栏 + - 左侧折叠式菜单 + - 右侧主内容区域 + +2. **交互功能** + - 菜单展开/收起动画 + - 页面内容切换(如等级设置页面) + - 开关按钮的切换效果 + - 搜索菜单功能 + +3. **响应式设计** + - 支持桌面端和移动端布局 + - 自适应屏幕大小 + +4. **用户体验** + - 平滑的动画过渡效果 + - 键盘快捷键支持(ESC回首页,Ctrl+F搜索) + - 通知提示系统 + +### 🎯 主要页面 + +- **首页**: 默认欢迎页面 +- **等级设置**: 会员等级管理表格,包含开关切换功能 + +### 🔧 菜单项 + +- 首页 +- 运营管理(可展开) +- 数据中心 +- 优惠券营销工具管理 +- 预售营销工具管理 +- 会员管理(可展开,包含等级设置等子菜单) +- 钱包管理(可展开) +- 运费管理(可展开) + +## 使用方法 + +1. **直接打开** + ```bash + # 在浏览器中打开 + open index.html + # 或者 + double-click index.html + ``` + +2. **本地服务器运行**(推荐) + ```bash + # 使用Python + python -m http.server 8000 + # 或使用Node.js + npx serve . + # 然后访问 http://localhost:8000 + ``` + +## 技术实现 + +- **HTML5**: 语义化标签结构 +- **CSS3**: 基于Tailwind CSS的样式系统,包含自定义动画 +- **JavaScript ES6+**: 原生JS实现所有交互功能 +- **响应式设计**: 适配不同设备屏幕 + +## 浏览器兼容性 + +- Chrome 60+ +- Firefox 55+ +- Safari 12+ +- Edge 79+ + +## 快捷键 + +- `ESC`: 返回首页 +- `Ctrl+F`: 聚焦搜索框 + +## 定制说明 + +如需修改样式或功能,可以编辑以下文件: +- `css/styles.css`: 修改样式 +- `js/main.js`: 修改交互逻辑 +- `index.html`: 修改页面结构 + +## 注意事项 + +1. 这是一个静态演示版本,所有数据都是模拟数据 +2. 开关切换、按钮点击等操作只有视觉反馈,不会实际提交数据 +3. 为了演示效果,保留了完整的交互逻辑和动画效果 + +## 原项目信息 + +- 原技术栈: Next.js + React + Tailwind CSS + shadcn/ui +- 转换时间: 2025年 +- 转换方式: 手动转换为纯HTML/CSS/JS \ No newline at end of file diff --git a/merchant/demo/css/styles.css b/merchant/demo/css/styles.css new file mode 100644 index 0000000..7175439 --- /dev/null +++ b/merchant/demo/css/styles.css @@ -0,0 +1,638 @@ +/* Reset and Base Styles */ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; + line-height: 1.5; + color: #111827; + background-color: #f9fafb; +} + +/* Utility Classes */ +.min-h-screen { + min-height: 100vh; +} + +.bg-gray-50 { + background-color: #f9fafb; +} + +.bg-green-700 { + background-color: #15803d; +} + +.bg-green-600 { + background-color: #16a34a; +} + +.bg-white { + background-color: #ffffff; +} + +.bg-gray-100 { + background-color: #f3f4f6; +} + +.bg-gray-200 { + background-color: #e5e7eb; +} + +.bg-gray-300 { + background-color: #d1d5db; +} + +.text-white { + color: #ffffff; +} + +.text-gray-500 { + color: #6b7280; +} + +.text-gray-600 { + color: #4b5563; +} + +.text-gray-700 { + color: #374151; +} + +.text-gray-900 { + color: #111827; +} + +.text-blue-500 { + color: #3b82f6; +} + +.text-green-600 { + color: #16a34a; +} + +.text-green-900 { + color: #14532d; +} + +.px-4 { + padding-left: 1rem; + padding-right: 1rem; +} + +.py-3 { + padding-top: 0.75rem; + padding-bottom: 0.75rem; +} + +.py-2 { + padding-top: 0.5rem; + padding-bottom: 0.5rem; +} + +.py-2\.5 { + padding-top: 0.625rem; + padding-bottom: 0.625rem; +} + +.py-4 { + padding-top: 1rem; + padding-bottom: 1rem; +} + +.py-6 { + padding-top: 1.5rem; + padding-bottom: 1.5rem; +} + +.px-3 { + padding-left: 0.75rem; + padding-right: 0.75rem; +} + +.px-6 { + padding-left: 1.5rem; + padding-right: 1.5rem; +} + +.p-2 { + padding: 0.5rem; +} + +.p-3 { + padding: 0.75rem; +} + +.p-6 { + padding: 1.5rem; +} + +.flex { + display: flex; +} + +.items-center { + align-items: center; +} + +.justify-between { + justify-content: space-between; +} + +.justify-center { + justify-content: center; +} + +.gap-2 { + gap: 0.5rem; +} + +.gap-3 { + gap: 0.75rem; +} + +.gap-4 { + gap: 1rem; +} + +.text-lg { + font-size: 1.125rem; + line-height: 1.75rem; +} + +.text-sm { + font-size: 0.875rem; + line-height: 1.25rem; +} + +.text-xs { + font-size: 0.75rem; + line-height: 1rem; +} + +.font-medium { + font-weight: 500; +} + +.h-4 { + height: 1rem; +} + +.w-4 { + width: 1rem; +} + +.h-3 { + height: 0.75rem; +} + +.w-3 { + width: 0.75rem; +} + +.h-8 { + height: 2rem; +} + +.w-8 { + width: 2rem; +} + +.h-16 { + height: 4rem; +} + +.w-16 { + width: 4rem; +} + +.h-96 { + height: 24rem; +} + +.h-full { + height: 100%; +} + +.w-full { + width: 100%; +} + +.w-48 { + width: 12rem; +} + +.w-11 { + width: 2.75rem; +} + +.h-6 { + height: 1.5rem; +} + +.h-5 { + height: 1.25rem; +} + +.w-5 { + width: 1.25rem; +} + +.rounded-md { + border-radius: 0.375rem; +} + +.rounded-lg { + border-radius: 0.5rem; +} + +.rounded-full { + border-radius: 9999px; +} + +.border { + border-width: 1px; +} + +.border-r { + border-right-width: 1px; +} + +.border-b { + border-bottom-width: 1px; +} + +.border-l-2 { + border-left-width: 2px; +} + +.border-gray-200 { + border-color: #e5e7eb; +} + +.border-gray-100 { + border-color: #f3f4f6; +} + +.border-gray-300 { + border-color: #d1d5db; +} + +.border-green-500 { + border-color: #22c55e; +} + +.shadow-sm { + box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05); +} + +.cursor-pointer { + cursor: pointer; +} + +.select-none { + user-select: none; +} + +.space-y-1 > * + * { + margin-top: 0.25rem; +} + +.flex-1 { + flex: 1 1 0%; +} + +.transition-transform { + transition-property: transform; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; +} + +.transition-colors { + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; +} + +.rotate-180 { + transform: rotate(180deg); +} + +.ml-4 { + margin-left: 1rem; +} + +.mt-2 { + margin-top: 0.5rem; +} + +.mb-4 { + margin-bottom: 1rem; +} + +.mx-auto { + margin-left: auto; + margin-right: auto; +} + +.text-center { + text-align: center; +} + +.text-left { + text-align: left; +} + +.uppercase { + text-transform: uppercase; +} + +.tracking-wider { + letter-spacing: 0.05em; +} + +.whitespace-nowrap { + white-space: nowrap; +} + +.overflow-x-auto { + overflow-x: auto; +} + +.divide-y > * + * { + border-top-width: 1px; +} + +.divide-gray-200 > * + * { + border-color: #e5e7eb; +} + +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border: 0; +} + +.peer:checked ~ .peer-checked\:bg-green-600 { + background-color: #16a34a; +} + +.peer-checked\:after\:translate-x-full { + content: ''; +} + +.peer:checked ~ .peer-checked\:after\:translate-x-full::after { + transform: translateX(100%); +} + +.peer-checked\:after\:border-white::after { + border-color: #ffffff; +} + +.after\:content-\[\'\'\]::after { + content: ''; +} + +.after\:absolute::after { + position: absolute; +} + +.after\:top-\[2px\]::after { + top: 2px; +} + +.after\:left-\[2px\]::after { + left: 2px; +} + +.after\:bg-white::after { + background-color: #ffffff; +} + +.after\:border-gray-300::after { + border-color: #d1d5db; +} + +.after\:border::after { + border-width: 1px; +} + +.after\:rounded-full::after { + border-radius: 9999px; +} + +.after\:h-5::after { + height: 1.25rem; +} + +.after\:w-5::after { + width: 1.25rem; +} + +.after\:transition-all::after { + transition-property: all; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; +} + +.peer-focus\:outline-none:focus ~ .peer-focus\:outline-none { + outline: 2px solid transparent; + outline-offset: 2px; +} + +.peer-focus\:ring-4:focus ~ .peer-focus\:ring-4 { + box-shadow: 0 0 0 4px; +} + +.peer-focus\:ring-green-300:focus ~ .peer-focus\:ring-green-300 { + box-shadow: 0 0 0 4px rgba(134, 239, 172, 0.5); +} + +.min-h-\[calc\(100vh-60px\)\] { + min-height: calc(100vh - 60px); +} + +.relative { + position: relative; +} + +.inline-flex { + display: inline-flex; +} + +.absolute { + position: absolute; +} + +.top-\[2px\] { + top: 2px; +} + +.left-\[2px\] { + left: 2px; +} + +.hidden { + display: none; +} + +/* Hover Effects */ +.hover\:bg-gray-50:hover { + background-color: #f9fafb; +} + +.hover\:bg-gray-100:hover { + background-color: #f3f4f6; +} + +.hover\:bg-green-600:hover { + background-color: #16a34a; +} + +.hover\:text-green-900:hover { + color: #14532d; +} + +/* Focus Effects */ +.focus\:border-green-500:focus { + border-color: #22c55e; +} + +.focus\:outline-none:focus { + outline: 2px solid transparent; + outline-offset: 2px; +} + +/* Custom Toggle Switch Styles */ +.toggle-switch { + position: relative; + display: inline-block; + width: 44px; + height: 24px; +} + +.toggle-switch input { + opacity: 0; + width: 0; + height: 0; +} + +.toggle-slider { + position: absolute; + cursor: pointer; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: #e5e7eb; + transition: .4s; + border-radius: 24px; +} + +.toggle-slider:before { + position: absolute; + content: ""; + height: 20px; + width: 20px; + left: 2px; + top: 2px; + background-color: white; + transition: .4s; + border-radius: 50%; + border: 1px solid #d1d5db; +} + +input:checked + .toggle-slider { + background-color: #16a34a; +} + +input:focus + .toggle-slider { + box-shadow: 0 0 0 4px rgba(134, 239, 172, 0.3); +} + +input:checked + .toggle-slider:before { + transform: translateX(20px); + border-color: white; +} + +/* Table Styles */ +table { + border-collapse: collapse; +} + +thead th { + background-color: #f9fafb; + font-weight: 500; + text-transform: uppercase; + letter-spacing: 0.05em; + font-size: 0.75rem; + color: #6b7280; + padding: 0.75rem 1.5rem; + text-align: left; +} + +tbody td { + padding: 1rem 1.5rem; + border-top: 1px solid #e5e7eb; + font-size: 0.875rem; +} + +tbody tr:hover { + background-color: #f9fafb; +} + +/* Button Styles */ +button { + border: none; + background: none; + cursor: pointer; + font-family: inherit; +} + +/* Input Styles */ +input[type="text"] { + border: 1px solid #e5e7eb; + border-radius: 0.375rem; + padding: 0.5rem 0.75rem; + font-size: 0.875rem; + width: 100%; + transition: border-color 0.15s ease; +} + +input[type="text"]:focus { + outline: none; + border-color: #22c55e; +} + +/* Animation */ +@keyframes fadeIn { + from { opacity: 0; } + to { opacity: 1; } +} + +.fade-in { + animation: fadeIn 0.3s ease-in; +} + +/* Responsive */ +@media (max-width: 768px) { + .w-48 { + width: 100%; + } + + .flex { + flex-direction: column; + } + + .min-h-\[calc\(100vh-60px\)\] { + min-height: auto; + } +} \ No newline at end of file diff --git a/merchant/demo/images/placeholder-logo.png b/merchant/demo/images/placeholder-logo.png new file mode 100644 index 0000000..8a792ac Binary files /dev/null and b/merchant/demo/images/placeholder-logo.png differ diff --git a/merchant/demo/images/placeholder-logo.svg b/merchant/demo/images/placeholder-logo.svg new file mode 100644 index 0000000..b1695aa --- /dev/null +++ b/merchant/demo/images/placeholder-logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/merchant/demo/images/placeholder-user.jpg b/merchant/demo/images/placeholder-user.jpg new file mode 100644 index 0000000..6fa7543 Binary files /dev/null and b/merchant/demo/images/placeholder-user.jpg differ diff --git a/merchant/demo/images/placeholder.jpg b/merchant/demo/images/placeholder.jpg new file mode 100644 index 0000000..6bfe963 Binary files /dev/null and b/merchant/demo/images/placeholder.jpg differ diff --git a/merchant/demo/images/placeholder.svg b/merchant/demo/images/placeholder.svg new file mode 100644 index 0000000..e763910 --- /dev/null +++ b/merchant/demo/images/placeholder.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/merchant/demo/index.html b/merchant/demo/index.html new file mode 100644 index 0000000..1ef5645 --- /dev/null +++ b/merchant/demo/index.html @@ -0,0 +1,305 @@ + + + + + + 大数集市商户端 + + + +
+ +
+
+

大数集市商户端

+
+ +
+ + + + +
+ 用户 +
+
+
+ +
+ + + + +
+ +
+
+
+ + + +

欢迎使用大数集市商户端

+

请从左侧菜单选择功能

+
+
+
+ + + +
+
+
+ + + + \ No newline at end of file diff --git a/merchant/demo/js/main.js b/merchant/demo/js/main.js new file mode 100644 index 0000000..6b0e0c0 --- /dev/null +++ b/merchant/demo/js/main.js @@ -0,0 +1,259 @@ +// 全局状态管理 +let currentExpandedMenus = []; +let currentSelectedMenuItem = ''; + +// DOM 加载完成后初始化 +document.addEventListener('DOMContentLoaded', function() { + console.log('大数集市商户端初始化完成'); + + // 初始化菜单状态 + initializeMenus(); + + // 初始化开关状态 + initializeSwitches(); + + // 添加搜索功能 + initializeSearch(); +}); + +// 菜单展开/收起功能 +function toggleMenu(menuId) { + const arrow = document.getElementById(menuId + '-arrow'); + const submenu = document.getElementById(menuId + '-submenu'); + + if (currentExpandedMenus.includes(menuId)) { + // 收起菜单 + currentExpandedMenus = currentExpandedMenus.filter(id => id !== menuId); + + if (arrow) { + arrow.classList.remove('rotate-180'); + } + + if (submenu) { + submenu.classList.add('hidden'); + } + } else { + // 展开菜单 + currentExpandedMenus.push(menuId); + + if (arrow) { + arrow.classList.add('rotate-180'); + } + + if (submenu) { + submenu.classList.remove('hidden'); + submenu.classList.add('fade-in'); + } + } + + console.log('菜单状态更新:', menuId, currentExpandedMenus); +} + +// 显示等级设置页面 +function showLevelSettings() { + // 隐藏默认内容 + const defaultContent = document.getElementById('default-content'); + const levelSettingsContent = document.getElementById('level-settings-content'); + + if (defaultContent) { + defaultContent.classList.add('hidden'); + } + + if (levelSettingsContent) { + levelSettingsContent.classList.remove('hidden'); + levelSettingsContent.classList.add('fade-in'); + } + + currentSelectedMenuItem = 'level-settings'; + console.log('切换到等级设置页面'); +} + +// 显示默认页面 +function showDefaultContent() { + const defaultContent = document.getElementById('default-content'); + const levelSettingsContent = document.getElementById('level-settings-content'); + + if (levelSettingsContent) { + levelSettingsContent.classList.add('hidden'); + } + + if (defaultContent) { + defaultContent.classList.remove('hidden'); + defaultContent.classList.add('fade-in'); + } + + currentSelectedMenuItem = ''; + console.log('切换到默认页面'); +} + +// 开关切换功能 +function toggleSwitch(switchElement) { + const isChecked = switchElement.checked; + console.log('开关状态:', isChecked); + + // 添加视觉反馈 + const slider = switchElement.nextElementSibling; + if (slider) { + if (isChecked) { + slider.style.backgroundColor = '#16a34a'; + } else { + slider.style.backgroundColor = '#e5e7eb'; + } + } +} + +// 初始化菜单状态 +function initializeMenus() { + // 会员管理菜单默认展开 + toggleMenu('member'); + + // 添加首页点击事件 + const homeMenuItem = document.querySelector('[onclick*="首页"]'); + if (homeMenuItem) { + homeMenuItem.addEventListener('click', showDefaultContent); + } + + console.log('菜单初始化完成'); +} + +// 初始化开关状态 +function initializeSwitches() { + const switches = document.querySelectorAll('input[type="checkbox"]'); + switches.forEach(switchElement => { + // 为已选中的开关设置正确的样式 + if (switchElement.checked) { + const slider = switchElement.nextElementSibling; + if (slider) { + slider.style.backgroundColor = '#16a34a'; + } + } + }); + + console.log('开关初始化完成,共', switches.length, '个开关'); +} + +// 搜索功能 +function initializeSearch() { + const searchInput = document.querySelector('input[placeholder*="搜索"]'); + if (searchInput) { + searchInput.addEventListener('input', function(e) { + const searchTerm = e.target.value.toLowerCase(); + filterMenuItems(searchTerm); + }); + } +} + +// 过滤菜单项 +function filterMenuItems(searchTerm) { + const menuItems = document.querySelectorAll('nav div'); + + menuItems.forEach(item => { + const text = item.textContent.toLowerCase(); + if (text.includes(searchTerm) || searchTerm === '') { + item.style.display = ''; + } else { + item.style.display = 'none'; + } + }); + + console.log('搜索筛选:', searchTerm); +} + +// 添加一些实用的辅助函数 +function showNotification(message, type = 'info') { + console.log('通知:', message, '类型:', type); + + // 创建通知元素 + const notification = document.createElement('div'); + notification.className = `notification ${type}`; + notification.textContent = message; + notification.style.cssText = ` + position: fixed; + top: 20px; + right: 20px; + padding: 12px 20px; + border-radius: 6px; + color: white; + font-size: 14px; + z-index: 1000; + transition: all 0.3s ease; + `; + + // 根据类型设置颜色 + switch(type) { + case 'success': + notification.style.backgroundColor = '#16a34a'; + break; + case 'error': + notification.style.backgroundColor = '#dc2626'; + break; + case 'warning': + notification.style.backgroundColor = '#d97706'; + break; + default: + notification.style.backgroundColor = '#3b82f6'; + } + + document.body.appendChild(notification); + + // 3秒后自动消失 + setTimeout(() => { + notification.style.opacity = '0'; + setTimeout(() => { + document.body.removeChild(notification); + }, 300); + }, 3000); +} + +// 等级明细设置功能 +function showLevelDetail(shopName) { + showNotification(`正在设置 ${shopName} 的等级明细`, 'info'); + console.log('设置等级明细:', shopName); +} + +// 添加表格行的点击事件 +document.addEventListener('DOMContentLoaded', function() { + const levelDetailButtons = document.querySelectorAll('button'); + levelDetailButtons.forEach(button => { + if (button.textContent.includes('设置等级明细')) { + button.addEventListener('click', function() { + const row = this.closest('tr'); + const shopName = row.querySelector('td').textContent; + showLevelDetail(shopName); + }); + } + }); +}); + +// 键盘快捷键支持 +document.addEventListener('keydown', function(e) { + // ESC键回到首页 + if (e.key === 'Escape') { + showDefaultContent(); + } + + // Ctrl+F 聚焦搜索框 + if (e.ctrlKey && e.key === 'f') { + e.preventDefault(); + const searchInput = document.querySelector('input[placeholder*="搜索"]'); + if (searchInput) { + searchInput.focus(); + } + } +}); + +// 窗口大小变化时的响应式处理 +window.addEventListener('resize', function() { + const sidebar = document.querySelector('aside'); + if (window.innerWidth < 768 && sidebar) { + console.log('切换到移动端布局'); + // 可以在这里添加移动端特定的逻辑 + } +}); + +// 导出一些全局函数供HTML调用 +window.toggleMenu = toggleMenu; +window.showLevelSettings = showLevelSettings; +window.showDefaultContent = showDefaultContent; +window.toggleSwitch = toggleSwitch; +window.showLevelDetail = showLevelDetail; \ No newline at end of file diff --git a/merchant/images/placeholder-logo.png b/merchant/images/placeholder-logo.png new file mode 100644 index 0000000..8a792ac Binary files /dev/null and b/merchant/images/placeholder-logo.png differ diff --git a/merchant/images/placeholder-logo.svg b/merchant/images/placeholder-logo.svg new file mode 100644 index 0000000..b1695aa --- /dev/null +++ b/merchant/images/placeholder-logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/merchant/images/placeholder-user.jpg b/merchant/images/placeholder-user.jpg new file mode 100644 index 0000000..6fa7543 Binary files /dev/null and b/merchant/images/placeholder-user.jpg differ diff --git a/merchant/images/placeholder.jpg b/merchant/images/placeholder.jpg new file mode 100644 index 0000000..6bfe963 Binary files /dev/null and b/merchant/images/placeholder.jpg differ diff --git a/merchant/images/placeholder.svg b/merchant/images/placeholder.svg new file mode 100644 index 0000000..e763910 --- /dev/null +++ b/merchant/images/placeholder.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/merchant/index.html b/merchant/index.html new file mode 100644 index 0000000..3662d1a --- /dev/null +++ b/merchant/index.html @@ -0,0 +1,201 @@ + + + + + + 大数集市商户端 + + + +
+ +
+
+

大数集市商户端

+
+ +
+ + + + +
+ 用户 +
+
+
+ +
+ + + + +
+ +
+
+
+ + + +

欢迎使用大数集市商户端

+

请从左侧菜单选择功能

+
+
+
+
+
+
+ + + + \ No newline at end of file diff --git a/merchant/js/common.js b/merchant/js/common.js new file mode 100644 index 0000000..63ece7a --- /dev/null +++ b/merchant/js/common.js @@ -0,0 +1,99 @@ +// 通用工具函数和组件 + +// 显示通知 +function showNotification(message, type = 'info') { + console.log('通知:', message, '类型:', type); + + // 创建通知元素 + const notification = document.createElement('div'); + notification.className = `notification ${type}`; + notification.textContent = message; + notification.style.cssText = ` + position: fixed; + top: 20px; + right: 20px; + padding: 12px 20px; + border-radius: 6px; + color: white; + font-size: 14px; + z-index: 1000; + transition: all 0.3s ease; + `; + + // 根据类型设置颜色 + switch(type) { + case 'success': + notification.style.backgroundColor = '#16a34a'; + break; + case 'error': + notification.style.backgroundColor = '#dc2626'; + break; + case 'warning': + notification.style.backgroundColor = '#d97706'; + break; + default: + notification.style.backgroundColor = '#3b82f6'; + } + + document.body.appendChild(notification); + + // 3秒后自动消失 + setTimeout(() => { + notification.style.opacity = '0'; + setTimeout(() => { + if (notification.parentNode) { + document.body.removeChild(notification); + } + }, 300); + }, 3000); +} + +// 开关切换功能 +function toggleSwitch(switchElement) { + const isChecked = switchElement.checked; + console.log('开关状态:', isChecked); + + // 添加视觉反馈 + const slider = switchElement.nextElementSibling; + if (slider) { + if (isChecked) { + slider.style.backgroundColor = '#16a34a'; + } else { + slider.style.backgroundColor = '#e5e7eb'; + } + } +} + +// 初始化开关状态 +function initializeSwitches() { + const switches = document.querySelectorAll('input[type="checkbox"]'); + switches.forEach(switchElement => { + // 为已选中的开关设置正确的样式 + if (switchElement.checked) { + const slider = switchElement.nextElementSibling; + if (slider) { + slider.style.backgroundColor = '#16a34a'; + } + } + }); + + console.log('开关初始化完成,共', switches.length, '个开关'); +} + +// 键盘快捷键支持 +document.addEventListener('keydown', function(e) { + // ESC键回到首页 + if (e.key === 'Escape') { + window.location.href = '../index.html'; + } +}); + +// DOM 加载完成后初始化 +document.addEventListener('DOMContentLoaded', function() { + console.log('页面初始化完成'); + initializeSwitches(); +}); + +// 导出全局函数 +window.showNotification = showNotification; +window.toggleSwitch = toggleSwitch; \ No newline at end of file diff --git a/merchant/js/main.js b/merchant/js/main.js new file mode 100644 index 0000000..908c243 --- /dev/null +++ b/merchant/js/main.js @@ -0,0 +1,192 @@ +// 主页面的JavaScript逻辑 - 简化版 + +// 全局状态管理 +let currentExpandedMenus = []; + +// DOM 加载完成后初始化 +document.addEventListener('DOMContentLoaded', function() { + console.log('大数集市商户端主页面初始化完成'); + + // 初始化菜单状态 + initializeMenus(); + + // 初始化开关状态 + initializeSwitches(); + + // 添加搜索功能 + initializeSearch(); +}); + +// 菜单展开/收起功能 +function toggleMenu(menuId) { + const arrow = document.getElementById(menuId + '-arrow'); + const submenu = document.getElementById(menuId + '-submenu'); + + if (currentExpandedMenus.includes(menuId)) { + // 收起菜单 + currentExpandedMenus = currentExpandedMenus.filter(id => id !== menuId); + + if (arrow) { + arrow.classList.remove('rotate-180'); + } + + if (submenu) { + submenu.classList.add('hidden'); + } + } else { + // 展开菜单 + currentExpandedMenus.push(menuId); + + if (arrow) { + arrow.classList.add('rotate-180'); + } + + if (submenu) { + submenu.classList.remove('hidden'); + submenu.classList.add('fade-in'); + } + } + + console.log('菜单状态更新:', menuId, currentExpandedMenus); +} + +// 开关切换功能 +function toggleSwitch(switchElement) { + const isChecked = switchElement.checked; + console.log('开关状态:', isChecked); + + // 添加视觉反馈 + const slider = switchElement.nextElementSibling; + if (slider) { + if (isChecked) { + slider.style.backgroundColor = '#16a34a'; + } else { + slider.style.backgroundColor = '#e5e7eb'; + } + } +} + +// 初始化菜单状态 +function initializeMenus() { + // 会员管理菜单默认展开 + toggleMenu('member'); + + console.log('菜单初始化完成'); +} + +// 初始化开关状态 +function initializeSwitches() { + const switches = document.querySelectorAll('input[type="checkbox"]'); + switches.forEach(switchElement => { + // 为已选中的开关设置正确的样式 + if (switchElement.checked) { + const slider = switchElement.nextElementSibling; + if (slider) { + slider.style.backgroundColor = '#16a34a'; + } + } + }); + + console.log('开关初始化完成,共', switches.length, '个开关'); +} + +// 搜索功能 +function initializeSearch() { + const searchInput = document.querySelector('input[placeholder*="搜索"]'); + if (searchInput) { + searchInput.addEventListener('input', function(e) { + const searchTerm = e.target.value.toLowerCase(); + filterMenuItems(searchTerm); + }); + } +} + +// 过滤菜单项 +function filterMenuItems(searchTerm) { + const menuItems = document.querySelectorAll('nav div'); + + menuItems.forEach(item => { + const text = item.textContent.toLowerCase(); + if (text.includes(searchTerm) || searchTerm === '') { + item.style.display = ''; + } else { + item.style.display = 'none'; + } + }); + + console.log('搜索筛选:', searchTerm); +} + +// 显示通知 +function showNotification(message, type = 'info') { + console.log('通知:', message, '类型:', type); + + // 创建通知元素 + const notification = document.createElement('div'); + notification.className = `notification ${type}`; + notification.textContent = message; + notification.style.cssText = ` + position: fixed; + top: 20px; + right: 20px; + padding: 12px 20px; + border-radius: 6px; + color: white; + font-size: 14px; + z-index: 1000; + transition: all 0.3s ease; + `; + + // 根据类型设置颜色 + switch(type) { + case 'success': + notification.style.backgroundColor = '#16a34a'; + break; + case 'error': + notification.style.backgroundColor = '#dc2626'; + break; + case 'warning': + notification.style.backgroundColor = '#d97706'; + break; + default: + notification.style.backgroundColor = '#3b82f6'; + } + + document.body.appendChild(notification); + + // 3秒后自动消失 + setTimeout(() => { + notification.style.opacity = '0'; + setTimeout(() => { + if (notification.parentNode) { + document.body.removeChild(notification); + } + }, 300); + }, 3000); +} + +// 键盘快捷键支持 +document.addEventListener('keydown', function(e) { + // Ctrl+F 聚焦搜索框 + if (e.ctrlKey && e.key === 'f') { + e.preventDefault(); + const searchInput = document.querySelector('input[placeholder*="搜索"]'); + if (searchInput) { + searchInput.focus(); + } + } +}); + +// 窗口大小变化时的响应式处理 +window.addEventListener('resize', function() { + const sidebar = document.querySelector('aside'); + if (window.innerWidth < 768 && sidebar) { + console.log('切换到移动端布局'); + // 可以在这里添加移动端特定的逻辑 + } +}); + +// 导出全局函数 +window.toggleMenu = toggleMenu; +window.toggleSwitch = toggleSwitch; +window.showNotification = showNotification; \ No newline at end of file diff --git a/merchant/js/member-tabs.js b/merchant/js/member-tabs.js new file mode 100644 index 0000000..7ff2538 --- /dev/null +++ b/merchant/js/member-tabs.js @@ -0,0 +1,2159 @@ +// Tab系统管理 - 会员管理模块 + +// Tab管理器类 +class MemberTabManager { + constructor() { + this.tabs = []; + this.activeTabId = ''; + this.tabCounter = 0; + } + + // 创建新tab + createTab(id, title, content, canClose = true) { + // 检查tab是否已存在 + const existingTab = this.tabs.find(tab => tab.id === id); + if (existingTab) { + this.showTab(id); + return existingTab; + } + + const tab = { + id: id, + title: title, + content: content, + canClose: canClose + }; + + this.tabs.push(tab); + this.renderTabs(); + this.showTab(id); + return tab; + } + + // 关闭tab + closeTab(tabId) { + const tabIndex = this.tabs.findIndex(tab => tab.id === tabId); + if (tabIndex === -1) return; + + const tab = this.tabs[tabIndex]; + if (!tab.canClose) return; + + this.tabs.splice(tabIndex, 1); + + // 如果关闭的是当前激活的tab,切换到其他tab + if (this.activeTabId === tabId) { + if (this.tabs.length > 0) { + this.showTab(this.tabs[this.tabs.length - 1].id); + } else { + this.showDefaultContent(); + } + } + + this.renderTabs(); + } + + // 显示指定tab + showTab(tabId) { + const tab = this.tabs.find(t => t.id === tabId); + if (!tab) return; + + this.activeTabId = tabId; + + // 更新tab激活状态 + document.querySelectorAll('.tab-item').forEach(tabEl => { + if (tabEl.dataset.tabId === tabId) { + tabEl.classList.add('border-green-500', 'text-green-600'); + tabEl.classList.remove('border-transparent', 'text-gray-500'); + } else { + tabEl.classList.remove('border-green-500', 'text-green-600'); + tabEl.classList.add('border-transparent', 'text-gray-500'); + } + }); + + // 更新内容区域 + const contentArea = document.getElementById('tab-content-area'); + if (contentArea) { + contentArea.innerHTML = tab.content; + } + + // 显示tab容器 + this.showTabContainer(); + } + + // 渲染tab导航 + renderTabs() { + const tabNav = document.getElementById('tab-nav'); + if (!tabNav) return; + + tabNav.innerHTML = ''; + + this.tabs.forEach(tab => { + const tabElement = document.createElement('div'); + tabElement.className = `tab-item flex items-center px-4 py-3 border-b-2 cursor-pointer transition-colors ${ + this.activeTabId === tab.id + ? 'border-green-500 text-green-600' + : 'border-transparent text-gray-500 hover:text-gray-700' + }`; + tabElement.dataset.tabId = tab.id; + + tabElement.innerHTML = ` + ${tab.title} + ${tab.canClose ? ` + + ` : ''} + `; + + tabElement.addEventListener('click', () => this.showTab(tab.id)); + tabNav.appendChild(tabElement); + }); + } + + // 显示tab容器 + showTabContainer() { + const tabContainer = document.getElementById('tab-container'); + if (tabContainer) { + tabContainer.classList.remove('hidden'); + tabContainer.classList.add('fade-in'); + } + } + + // 显示默认内容 + showDefaultContent() { + const tabContainer = document.getElementById('tab-container'); + if (tabContainer) { + const contentArea = document.getElementById('tab-content-area'); + if (contentArea) { + contentArea.innerHTML = ` +
+
+ + + + + +

会员管理

+

请从左侧菜单选择功能

+
+
+ `; + } + } + + this.activeTabId = ''; + this.tabs = []; + this.renderTabs(); + } + + // 清空所有tabs + clearAllTabs() { + this.tabs = []; + this.activeTabId = ''; + this.showDefaultContent(); + } +} + +// 创建全局tab管理器实例 +const memberTabManager = new MemberTabManager(); + +// 打开等级设置Tab +function openLevelSettingsTab() { + const tabId = 'level-settings'; + + const content = ` +
+
+

等级设置

+
+ + +
+
+ +
+ +
+
+
+
+ + +
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ 摊位名称 + + 是否启用会员 + + 会员等级 + + 操作 +
时尚服装店 + + lv1, lv2, lv3, lv4 + +
数码电子城 + + lv1, lv2, lv3 + +
美食餐厅 + + lv1, lv2, lv3, lv4 + +
家居生活馆 + + lv1, lv2 + +
运动健身店 + + lv1, lv2, lv3, lv4 + +
+
+
+ `; + + memberTabManager.createTab(tabId, '等级设置', content, false); +} + +// 打开等级明细tab +function openLevelDetailTab(shopName) { + const tabId = `level-detail-${shopName}`; + + // 生成模拟数据 + const mockLevels = [ + { name: 'LV1', growth: 100, members: 1250, benefits: '9.5折优惠' }, + { name: 'LV2', growth: 500, members: 850, benefits: '9折优惠, 积分双倍' }, + { name: 'LV3', growth: 1200, members: 450, benefits: '8.5折优惠, 积分双倍, 生日优惠券' }, + { name: 'LV4', growth: 2500, members: 180, benefits: '8折优惠, 积分三倍, 生日优惠券, 专属客服' } + ]; + + const content = ` +
+
+

${shopName} - 等级设置明细

+
+ + +
+
+ +
+ + + + + + + + + + + ${mockLevels.map(level => ` + + + + + + + `).join('')} + +
等级名称所需成长值会员人数会员权益
${level.name}${level.growth}${level.members}${level.benefits}
+
+
+ `; + + memberTabManager.createTab(tabId, `${shopName} - 等级明细`, content, true); +} + +// 打开等级编辑Tab +function openLevelEditTab(shopName) { + const tabId = `level-edit-${shopName}`; + + // 生成模拟等级编辑数据 + const mockEditLevels = [ + { + level: 'LV1', + name: '铜牌会员', + growthMin: 0, + growthMax: 100, + memberDiscount: true, + discountRate: 5, + pointExchange: false, + birthdayCoupon: false, + birthdayDoublePoints: false + }, + { + level: 'LV2', + name: '银牌会员', + growthMin: 101, + growthMax: 500, + memberDiscount: true, + discountRate: 10, + pointExchange: true, + birthdayCoupon: true, + birthdayDoublePoints: true + }, + { + level: 'LV3', + name: '金牌会员', + growthMin: 501, + growthMax: 1200, + memberDiscount: true, + discountRate: 15, + pointExchange: true, + birthdayCoupon: true, + birthdayDoublePoints: true + }, + { + level: 'LV4', + name: '钻石会员', + growthMin: 1201, + growthMax: 9999, + memberDiscount: true, + discountRate: 20, + pointExchange: true, + birthdayCoupon: true, + birthdayDoublePoints: true + } + ]; + + const content = ` +
+
+

${shopName} - 等级编辑

+
+ + +
+
+ +
+ + + + + + + + + + + + + + + + ${mockEditLevels.map(level => ` + + + + + + + + + + + + `).join('')} + +
等级等级名称成长值范围开启会员折扣折扣率(%)开启积分兑换开启生日优惠券生日优惠券操作开启生日双倍积分
${level.level} + + +
+ + - + +
+
+ + + + + + + + + + + +
+
+
+ `; + + memberTabManager.createTab(tabId, `${shopName} - 等级编辑`, content, true); +} + +// 打开优惠券弹窗 +function openCouponModal(level) { + const modal = document.getElementById('coupon-modal'); + if (modal) { + modal.classList.remove('hidden'); + resetCouponForm(); + console.log(`为等级 ${level} 添加优惠券`); + } +} + +// 测试优惠券弹窗功能 +function testCouponModal() { + openCouponModal('TEST'); +} + +// 优惠券相关函数 +function closeCouponModal(event) { + if (event && event.target !== event.currentTarget) { + return; + } + + const modal = document.getElementById('coupon-modal'); + if (modal) { + modal.classList.add('hidden'); + } +} + +function resetCouponForm() { + document.getElementById('coupon-name').value = '生日优惠券'; + document.getElementById('coupon-threshold').value = '10'; + document.getElementById('coupon-discount').value = '1'; + document.getElementById('coupon-validity').value = '1'; +} + +function adjustThreshold(delta) { + const input = document.getElementById('coupon-threshold'); + if (input) { + const currentValue = parseInt(input.value) || 0; + const newValue = Math.max(0, currentValue + delta); + input.value = newValue; + } +} + +function adjustDiscount(delta) { + const input = document.getElementById('coupon-discount'); + if (input) { + const currentValue = parseInt(input.value) || 0; + const newValue = Math.max(0, currentValue + delta); + input.value = newValue; + } +} + +function submitCoupon() { + const couponData = { + name: document.getElementById('coupon-name').value, + threshold: document.getElementById('coupon-threshold').value, + discount: document.getElementById('coupon-discount').value, + validity: document.getElementById('coupon-validity').value + }; + + if (!couponData.name.trim()) { + showNotification('请输入优惠券名称', 'error'); + return; + } + + if (parseInt(couponData.discount) >= parseInt(couponData.threshold)) { + showNotification('减免金额不能大于或等于门槛金额', 'error'); + return; + } + + showNotification(`成功添加优惠券:${couponData.name}`, 'success'); + closeCouponModal(); +} + +function submitLevelDetail(shopName) { + showNotification(`${shopName} 等级明细已提交`, 'success'); +} + +function submitLevelEdit(shopName) { + showNotification(`${shopName} 等级编辑已提交`, 'success'); +} + +// 摊位筛选相关功能 +let selectedStalls = []; +let stallDropdownOpen = false; + +function toggleStallDropdown(event) { + event.preventDefault(); + const select = document.getElementById('stall-filter'); + const selectedDiv = document.getElementById('selected-stalls'); + + if (!stallDropdownOpen) { + select.size = 6; + stallDropdownOpen = true; + + // 添加点击事件监听器 + document.addEventListener('click', closeStallDropdown); + } +} + +function closeStallDropdown(event) { + const select = document.getElementById('stall-filter'); + const selectedDiv = document.getElementById('selected-stalls'); + + if (!select || !select.contains(event.target)) { + select.size = 1; + stallDropdownOpen = false; + document.removeEventListener('click', closeStallDropdown); + } +} + +// 处理多选选项 +document.addEventListener('change', function(event) { + if (event.target.id === 'stall-filter') { + const select = event.target; + const selectedOptions = Array.from(select.selectedOptions); + const selectedDiv = document.getElementById('selected-stalls'); + + selectedStalls = selectedOptions + .filter(option => option.value && option.value !== '') + .map(option => option.value); + + updateSelectedStallsDisplay(); + } +}); + +function updateSelectedStallsDisplay() { + const selectedDiv = document.getElementById('selected-stalls'); + if (!selectedDiv) return; + + selectedDiv.innerHTML = ''; + + selectedStalls.forEach(stall => { + const tag = document.createElement('span'); + tag.className = 'inline-flex items-center px-2 py-1 rounded-md text-xs font-medium bg-green-100 text-green-800'; + tag.innerHTML = ` + ${stall} + + `; + selectedDiv.appendChild(tag); + }); +} + +function removeSelectedStall(stallName) { + selectedStalls = selectedStalls.filter(stall => stall !== stallName); + + // 更新select控件的选中状态 + const select = document.getElementById('stall-filter'); + if (select) { + Array.from(select.options).forEach(option => { + if (option.value === stallName) { + option.selected = false; + } + }); + } + + updateSelectedStallsDisplay(); +} + +function filterStallTable() { + const tableRows = document.querySelectorAll('#tab-content-area tbody tr'); + + if (selectedStalls.length === 0) { + // 如果没有选择任何摊位,显示所有行 + tableRows.forEach(row => { + row.style.display = ''; + }); + showNotification('已显示所有摊位', 'info'); + } else { + // 根据选择的摊位筛选表格行 + let visibleCount = 0; + tableRows.forEach(row => { + const stallNameCell = row.querySelector('td:first-child'); + if (stallNameCell) { + const stallName = stallNameCell.textContent.trim(); + if (selectedStalls.includes(stallName)) { + row.style.display = ''; + visibleCount++; + } else { + row.style.display = 'none'; + } + } + }); + showNotification(`已筛选显示 ${visibleCount} 个摊位`, 'success'); + } +} + +// 打开批量会员等级编辑Tab +function openBatchLevelEditTab() { + const tabId = 'batch-level-edit'; + + // 生成摊位数据 + const stallOptions = [ + '新世纪电子城', + '金辉服装店', + '华联超市', + '美味餐厅', + '家具城', + '运动专营店', + '书香文具店', + '花园茶社' + ]; + + // 生成等级编辑数据(与等级编辑页面内容一致) + const mockEditLevels = [ + { + level: 'LV1', + name: '铜牌会员', + growthMin: 0, + growthMax: 100, + memberDiscount: true, + discountRate: 5, + pointExchange: false, + birthdayCoupon: false, + birthdayDoublePoints: false + }, + { + level: 'LV2', + name: '银牌会员', + growthMin: 101, + growthMax: 500, + memberDiscount: true, + discountRate: 10, + pointExchange: true, + birthdayCoupon: true, + birthdayDoublePoints: true + }, + { + level: 'LV3', + name: '金牌会员', + growthMin: 501, + growthMax: 1200, + memberDiscount: true, + discountRate: 15, + pointExchange: true, + birthdayCoupon: true, + birthdayDoublePoints: true + }, + { + level: 'LV4', + name: '钻石会员', + growthMin: 1201, + growthMax: 9999, + memberDiscount: true, + discountRate: 20, + pointExchange: true, + birthdayCoupon: true, + birthdayDoublePoints: true + } + ]; + + const content = ` +
+
+

批量会员等级编辑

+
+ + +
+
+ + +
+
+ +
+ + +
+
+
+
+ +
+
+ + +
+ + + + + + + + + + + + + + + + ${mockEditLevels.map(level => ` + + + + + + + + + + + + `).join('')} + +
等级等级名称成长值范围开启会员折扣折扣率(%)开启积分兑换开启生日优惠券生日优惠券操作开启生日双倍积分
${level.level} + + +
+ + - + +
+
+ + + + + + + + + + + +
+
+
+ `; + + memberTabManager.createTab(tabId, '批量会员等级编辑', content, true); + + // 初始化批量选择的摊位显示(默认全选) + setTimeout(() => { + batchSelectedStalls = [...stallOptions]; + updateBatchSelectedStallsDisplay(); + }, 100); +} + +// 批量编辑相关的全局变量 +let batchSelectedStalls = []; +let batchDropdownOpen = false; + +// 批量摊位选择相关功能 +function toggleBatchStallDropdown() { + const dropdown = document.getElementById('batch-stall-dropdown-list'); + const button = document.getElementById('batch-stall-dropdown-btn'); + + if (dropdown && button) { + batchDropdownOpen = !batchDropdownOpen; + if (batchDropdownOpen) { + dropdown.classList.remove('hidden'); + setTimeout(() => { + document.addEventListener('click', closeBatchDropdownOnClickOutside); + }, 0); + } else { + dropdown.classList.add('hidden'); + document.removeEventListener('click', closeBatchDropdownOnClickOutside); + } + } +} + +function closeBatchDropdownOnClickOutside(event) { + const dropdown = document.getElementById('batch-stall-dropdown-list'); + const button = document.getElementById('batch-stall-dropdown-btn'); + + if (dropdown && button && !dropdown.contains(event.target) && !button.contains(event.target)) { + dropdown.classList.add('hidden'); + batchDropdownOpen = false; + document.removeEventListener('click', closeBatchDropdownOnClickOutside); + } +} + +function updateBatchSelectedStalls() { + const checkboxes = document.querySelectorAll('#batch-stall-dropdown-list input[type="checkbox"]'); + batchSelectedStalls = []; + + checkboxes.forEach(checkbox => { + if (checkbox.checked) { + batchSelectedStalls.push(checkbox.value); + } + }); + + updateBatchDropdownText(); + updateBatchSelectedStallsDisplay(); +} + +function updateBatchDropdownText() { + const dropdownText = document.getElementById('batch-dropdown-text'); + if (dropdownText) { + if (batchSelectedStalls.length === 0) { + dropdownText.textContent = '请选择摊位...'; + } else if (batchSelectedStalls.length === 8) { + dropdownText.textContent = '全部选择'; + } else if (batchSelectedStalls.length === 1) { + dropdownText.textContent = batchSelectedStalls[0]; + } else { + dropdownText.textContent = `已选择 ${batchSelectedStalls.length} 个摊位`; + } + } +} + +function updateBatchSelectedStallsDisplay() { + const selectedDiv = document.getElementById('batch-selected-stalls'); + if (!selectedDiv) return; + + selectedDiv.innerHTML = ''; + + batchSelectedStalls.forEach(stall => { + const tag = document.createElement('span'); + tag.className = 'inline-flex items-center px-2 py-1 rounded-md text-xs font-medium bg-blue-100 text-blue-800'; + tag.innerHTML = ` + ${stall} + + `; + selectedDiv.appendChild(tag); + }); +} + +function removeBatchSelectedStall(stallName) { + batchSelectedStalls = batchSelectedStalls.filter(stall => stall !== stallName); + + // 更新checkbox状态 + const checkboxes = document.querySelectorAll('#batch-stall-dropdown-list input[type="checkbox"]'); + checkboxes.forEach(checkbox => { + if (checkbox.value === stallName) { + checkbox.checked = false; + } + }); + + updateBatchDropdownText(); + updateBatchSelectedStallsDisplay(); +} + +function submitBatchLevelEdit() { + if (batchSelectedStalls.length === 0) { + showNotification('请至少选择一个摊位', 'error'); + return; + } + + const selectedStallsText = batchSelectedStalls.length === 8 ? '全部摊位' : `${batchSelectedStalls.length}个摊位`; + showNotification(`批量等级编辑已提交,将应用到${selectedStallsText}`, 'success'); +} + +// 打开会员列表Tab +function openMemberListTab() { + const tabId = 'member-list'; + + // 生成模拟会员数据 + const mockMembers = [ + { + id: 'M001', + avatar: 'https://ui-avatars.com/api/?name=张三&background=random', + nickname: '张三', + phone: '138****1234', + stall: '时尚服装店', + level: 'LV2', + birthday: '1990-05-15', + registerTime: '2024-01-15 14:30:25' + }, + { + id: 'M002', + avatar: 'https://ui-avatars.com/api/?name=李四&background=random', + nickname: '李四', + phone: '139****5678', + stall: '数码电子城', + level: 'LV1', + birthday: '1985-08-20', + registerTime: '2024-02-20 09:15:30' + }, + { + id: 'M003', + avatar: 'https://ui-avatars.com/api/?name=王五&background=random', + nickname: '王五', + phone: '136****9012', + stall: '美食餐厅', + level: 'LV3', + birthday: '1992-12-08', + registerTime: '2024-03-10 16:45:12' + }, + { + id: 'M004', + avatar: 'https://ui-avatars.com/api/?name=赵六&background=random', + nickname: '赵六', + phone: '137****3456', + stall: '家居生活馆', + level: 'LV1', + birthday: '1988-03-25', + registerTime: '2024-04-05 11:20:45' + }, + { + id: 'M005', + avatar: 'https://ui-avatars.com/api/?name=孙七&background=random', + nickname: '孙七', + phone: '135****7890', + stall: '运动健身店', + level: 'LV4', + birthday: '1995-07-12', + registerTime: '2024-05-22 13:55:18' + }, + { + id: 'M006', + avatar: 'https://ui-avatars.com/api/?name=周八&background=random', + nickname: '周八', + phone: '134****2468', + stall: '时尚服装店', + level: 'LV2', + birthday: '1991-11-30', + registerTime: '2024-06-18 08:35:22' + } + ]; + + const content = ` +
+
+

会员列表

+
+ + +
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+ + +
+
+ + +
+
+
+
+ + + + + +
+
+

会员总数

+

1,247

+
+
+
+
+
+
+ + + +
+
+

今日新增

+

23

+
+
+
+
+ + +
+
+ + + + + + + + + + + + + + + + + ${mockMembers.map(member => ` + + + + + + + + + + + + + `).join('')} + +
+ + + 所属摊位 + + + + + 用户ID + + + + + 用户头像 + + 用户昵称 + + + + + 手机号 + + 会员等级 + + + + + 生日 + + 注册时间 + + + + + 操作 +
+ + ${member.stall}${member.id} + ${member.nickname} + ${member.nickname}${member.phone} + + ${member.level} + + ${member.birthday}${member.registerTime} + +
+
+ + +
+
+
+ 显示 + + 条记录,共 1,247 +
+
+ + + + 第 页,共 63 页 + + + +
+
+
+
+
+ `; + + memberTabManager.createTab(tabId, '会员列表', content, false); + + // 初始化分页变量 + setTimeout(() => { + initializeMemberListPagination(); + }, 100); +} + +// 获取等级徽章颜色 +function getLevelBadgeColor(level) { + const colors = { + 'LV1': 'bg-gray-100 text-gray-800', + 'LV2': 'bg-blue-100 text-blue-800', + 'LV3': 'bg-green-100 text-green-800', + 'LV4': 'bg-purple-100 text-purple-800' + }; + return colors[level] || 'bg-gray-100 text-gray-800'; +} + +// 分页相关变量 +let currentPage = 1; +let pageSize = 20; +let totalPages = 63; +let totalRecords = 1247; + +// 初始化分页 +function initializeMemberListPagination() { + updatePaginationDisplay(); +} + +// 更新分页显示 +function updatePaginationDisplay() { + document.getElementById('current-page-input').value = currentPage; + document.getElementById('total-pages').textContent = totalPages; + document.getElementById('total-records').textContent = totalRecords.toLocaleString(); + + // 更新按钮状态 + const firstBtn = document.getElementById('first-page'); + const prevBtn = document.getElementById('prev-page'); + const nextBtn = document.getElementById('next-page'); + const lastBtn = document.getElementById('last-page'); + + if (firstBtn) firstBtn.disabled = currentPage === 1; + if (prevBtn) prevBtn.disabled = currentPage === 1; + if (nextBtn) nextBtn.disabled = currentPage === totalPages; + if (lastBtn) lastBtn.disabled = currentPage === totalPages; +} + +// 跳转到指定页面 +function goToPage(page) { + const pageNum = parseInt(page); + if (pageNum >= 1 && pageNum <= totalPages) { + currentPage = pageNum; + updatePaginationDisplay(); + showNotification(`已跳转到第 ${currentPage} 页`, 'info'); + } +} + +// 改变每页显示数量 +function changePageSize(size) { + pageSize = parseInt(size); + totalPages = Math.ceil(totalRecords / pageSize); + currentPage = 1; + updatePaginationDisplay(); + showNotification(`每页显示 ${pageSize} 条记录`, 'info'); +} + +// 筛选会员列表 +function filterMemberList() { + const stallFilter = document.getElementById('member-stall-filter').value; + const nicknameFilter = document.getElementById('member-nickname-filter').value.toLowerCase(); + const levelFilter = document.getElementById('member-level-filter').value; + const registerFilter = document.getElementById('member-register-filter').value; + + const rows = document.querySelectorAll('.member-row'); + let visibleCount = 0; + + rows.forEach(row => { + const stall = row.dataset.stall; + const nickname = row.dataset.nickname.toLowerCase(); + const level = row.dataset.level; + const registerDate = row.dataset.registerDate; + + let shouldShow = true; + + if (stallFilter && stall !== stallFilter) shouldShow = false; + if (nicknameFilter && !nickname.includes(nicknameFilter)) shouldShow = false; + if (levelFilter && level !== levelFilter) shouldShow = false; + if (registerFilter && registerDate !== registerFilter) shouldShow = false; + + if (shouldShow) { + row.style.display = ''; + visibleCount++; + } else { + row.style.display = 'none'; + } + }); + + showNotification(`筛选完成,显示 ${visibleCount} 条记录`, 'success'); +} + +// 重置筛选条件 +function resetMemberFilters() { + document.getElementById('member-stall-filter').value = ''; + document.getElementById('member-nickname-filter').value = ''; + document.getElementById('member-level-filter').value = ''; + document.getElementById('member-register-filter').value = ''; + + // 显示所有行 + const rows = document.querySelectorAll('.member-row'); + rows.forEach(row => { + row.style.display = ''; + }); + + showNotification('筛选条件已重置', 'info'); +} + +// 全选/取消全选 +function toggleAllMembers(checkbox) { + const memberCheckboxes = document.querySelectorAll('.member-checkbox'); + memberCheckboxes.forEach(cb => { + cb.checked = checkbox.checked; + }); + + const selectedCount = checkbox.checked ? memberCheckboxes.length : 0; + showNotification(`已${checkbox.checked ? '选中' : '取消选中'} ${selectedCount} 个会员`, 'info'); +} + +// 表格排序 +let sortDirection = {}; +function sortMemberTable(column) { + const direction = sortDirection[column] === 'asc' ? 'desc' : 'asc'; + sortDirection[column] = direction; + + showNotification(`按${column}${direction === 'asc' ? '升序' : '降序'}排序`, 'info'); +} + +// 查看会员详情 +function viewMemberDetail(memberId) { + // 获取会员模拟数据 + const memberData = getMemberDataById(memberId); + if (!memberData) { + showNotification('会员信息不存在', 'error'); + return; + } + + openMemberDetailTab(memberData); +} + +// 获取会员数据(模拟数据) +function getMemberDataById(memberId) { + const mockMemberDetails = { + 'M001': { + id: 'M001', + name: '张三', + phone: '138****1234', + registerDate: '2024-01-15', + birthday: '1990-05-15', + growth: 1250, + points: 890, + coupons: 5 + }, + 'M002': { + id: 'M002', + name: '李四', + phone: '139****5678', + registerDate: '2024-02-20', + birthday: '1985-08-20', + growth: 680, + points: 450, + coupons: 3 + }, + 'M003': { + id: 'M003', + name: '王五', + phone: '136****9012', + registerDate: '2024-03-10', + birthday: '1992-12-08', + growth: 2100, + points: 1200, + coupons: 8 + }, + 'M004': { + id: 'M004', + name: '赵六', + phone: '137****3456', + registerDate: '2024-04-05', + birthday: '1988-03-25', + growth: 350, + points: 280, + coupons: 2 + }, + 'M005': { + id: 'M005', + name: '孙七', + phone: '135****7890', + registerDate: '2024-05-22', + birthday: '1995-07-12', + growth: 3200, + points: 1650, + coupons: 12 + }, + 'M006': { + id: 'M006', + name: '周八', + phone: '134****2468', + registerDate: '2024-06-18', + birthday: '1991-11-30', + growth: 920, + points: 560, + coupons: 4 + } + }; + + return mockMemberDetails[memberId]; +} + +// 打开会员详情Tab +function openMemberDetailTab(memberData) { + const tabId = `member-detail-${memberData.id}`; + const tabTitle = `会员详情-${memberData.name}`; + + // 生成优惠券数据 + const couponData = generateMemberCoupons(memberData.coupons); + + // 生成成长值明细数据 + const growthDetailData = generateGrowthDetails(memberData.growth); + + // 生成积分明细数据 + const pointDetailData = generatePointDetails(memberData.points); + + const content = ` +
+
+

${tabTitle}

+ +
+ + +
+

会员信息

+
+
+ 会员名称 + ${memberData.name} +
+
+ 会员手机号 + ${memberData.phone} +
+
+ 会员注册日期 + ${memberData.registerDate} +
+
+ 会员生日 + ${memberData.birthday} +
+
+
+ + +
+

会员资产

+
+
+
+
+ + + +
+
+

会员成长值

+

${memberData.growth}

+
+
+
+
+
+
+ + + +
+
+

会员积分

+

${memberData.points}

+
+
+
+
+
+
+ + + +
+
+

会员优惠券

+

${memberData.coupons}

+
+
+
+
+
+ + +
+
+ +
+ + +
+ +
+
+ + + + + + + + + + + ${growthDetailData.map(item => ` + + + + + + + `).join('')} + +
变化时间成长值增加关联订单详情
${item.time}+${item.growth}${item.orderId || '无'} + +
+
+ + +
+
+ 共 ${growthDetailData.length} 条记录 +
+
+ + 第 1 页,共 1 页 + +
+
+
+ + + +
+
+
+ `; + + memberTabManager.createTab(tabId, tabTitle, content, true); +} + +// 生成会员优惠券数据 +function generateMemberCoupons(count) { + const couponTypes = ['满减券', '折扣券', '生日券', '新人券', '节日券']; + const coupons = []; + + for (let i = 0; i < count; i++) { + const type = couponTypes[Math.floor(Math.random() * couponTypes.length)]; + const issueDate = new Date(2024, Math.floor(Math.random() * 12), Math.floor(Math.random() * 28) + 1); + const validityDays = Math.floor(Math.random() * 90) + 30; + const expiryDate = new Date(issueDate.getTime() + validityDays * 24 * 60 * 60 * 1000); + + coupons.push({ + id: `C${String(i + 1).padStart(3, '0')}`, + name: `${type}${i + 1}`, + issueDate: issueDate.toISOString().split('T')[0], + expiryDate: expiryDate.toISOString().split('T')[0], + content: getRandomCouponContent(type) + }); + } + + return coupons; +} + +// 获取随机优惠券内容 +function getRandomCouponContent(type) { + const contents = { + '满减券': ['满100减20', '满200减50', '满500减100'], + '折扣券': ['9折优惠', '8.5折优惠', '8折优惠'], + '生日券': ['生日专享8折', '生日满100减30'], + '新人券': ['新人专享9折', '新人满50减10'], + '节日券': ['节日满200减30', '节日8.8折优惠'] + }; + + const typeContents = contents[type] || ['优惠券']; + return typeContents[Math.floor(Math.random() * typeContents.length)]; +} + +// 生成成长值明细数据 +function generateGrowthDetails(totalGrowth) { + const details = []; + const reasons = [ + { type: 'register', reason: '注册奖励', growth: 50, hasOrder: false }, + { type: 'birthday', reason: '生日奖励', growth: 100, hasOrder: false }, + { type: 'order', reason: '订单消费', growth: null, hasOrder: true }, + { type: 'activity', reason: '活动奖励', growth: 20, hasOrder: false } + ]; + + let currentGrowth = 0; + let id = 1; + + while (currentGrowth < totalGrowth && details.length < 20) { + const reasonData = reasons[Math.floor(Math.random() * reasons.length)]; + let growth = reasonData.growth; + + if (reasonData.type === 'order') { + growth = Math.floor(Math.random() * 100) + 10; + } + + if (currentGrowth + growth > totalGrowth) { + growth = totalGrowth - currentGrowth; + } + + const days = Math.floor(Math.random() * 180); + const time = new Date(Date.now() - days * 24 * 60 * 60 * 1000); + + details.push({ + id: `G${String(id).padStart(3, '0')}`, + time: time.toISOString().split('T')[0] + ' ' + time.toTimeString().split(' ')[0].substring(0, 5), + growth: growth, + orderId: reasonData.hasOrder ? `ORD${String(Math.floor(Math.random() * 9999) + 1).padStart(4, '0')}` : null, + type: reasonData.type, + reason: reasonData.reason + }); + + currentGrowth += growth; + id++; + } + + return details.sort((a, b) => new Date(b.time) - new Date(a.time)); +} + +// 生成积分明细数据 +function generatePointDetails(totalPoints) { + const details = []; + const reasons = [ + { type: 'register', reason: '注册奖励', points: 100, hasOrder: false }, + { type: 'birthday', reason: '生日奖励', points: 200, hasOrder: false }, + { type: 'order_earn', reason: '订单获得积分', points: null, hasOrder: true }, + { type: 'order_use', reason: '积分抵扣', points: null, hasOrder: true, isNegative: true }, + { type: 'activity', reason: '活动奖励', points: 50, hasOrder: false } + ]; + + let currentPoints = 0; + let id = 1; + + while (details.length < 25) { + const reasonData = reasons[Math.floor(Math.random() * reasons.length)]; + let points = reasonData.points; + + if (reasonData.type === 'order_earn') { + points = Math.floor(Math.random() * 200) + 20; + } else if (reasonData.type === 'order_use') { + points = -(Math.floor(Math.random() * 150) + 10); + } + + const days = Math.floor(Math.random() * 180); + const time = new Date(Date.now() - days * 24 * 60 * 60 * 1000); + + details.push({ + id: `P${String(id).padStart(3, '0')}`, + time: time.toISOString().split('T')[0] + ' ' + time.toTimeString().split(' ')[0].substring(0, 5), + change: points, + orderId: reasonData.hasOrder ? `ORD${String(Math.floor(Math.random() * 9999) + 1).padStart(4, '0')}` : null, + type: reasonData.type, + reason: reasonData.reason + }); + + currentPoints += points; + id++; + } + + return details.sort((a, b) => new Date(b.time) - new Date(a.time)); +} + +// 切换详情Tab +function switchDetailTab(tabType, memberId) { + // 更新按钮状态 + const allTabs = document.querySelectorAll(`#growth-tab-${memberId}, #points-tab-${memberId}`); + allTabs.forEach(tab => { + tab.classList.remove('active', 'border-green-500', 'text-green-600'); + tab.classList.add('border-transparent', 'text-gray-500'); + }); + + const activeTab = document.getElementById(`${tabType}-tab-${memberId}`); + if (activeTab) { + activeTab.classList.add('active', 'border-green-500', 'text-green-600'); + activeTab.classList.remove('border-transparent', 'text-gray-500'); + } + + // 切换内容 + const allContents = document.querySelectorAll(`#growth-content-${memberId}, #points-content-${memberId}`); + allContents.forEach(content => { + content.classList.add('hidden'); + }); + + const activeContent = document.getElementById(`${tabType}-content-${memberId}`); + if (activeContent) { + activeContent.classList.remove('hidden'); + } +} + +// 显示优惠券弹窗 +function showMemberCouponsModal(memberId) { + const memberData = getMemberDataById(memberId); + if (!memberData) return; + + const coupons = generateMemberCoupons(memberData.coupons); + + const modalHtml = ` +
+
+
+

${memberData.name} - 优惠券列表

+ +
+ +
+ + + + + + + + + + + ${coupons.map(coupon => ` + + + + + + + `).join('')} + +
优惠券名称发放日期有效期优惠券内容
${coupon.name}${coupon.issueDate}${coupon.expiryDate}${coupon.content}
+
+ +
+ +
+
+
+ `; + + // 添加到页面 + const existingModal = document.getElementById('member-coupons-modal'); + if (existingModal) { + existingModal.remove(); + } + + document.body.insertAdjacentHTML('beforeend', modalHtml); +} + +// 关闭优惠券弹窗 +function closeMemberCouponsModal(event) { + if (event && event.target !== event.currentTarget) { + return; + } + + const modal = document.getElementById('member-coupons-modal'); + if (modal) { + modal.remove(); + } +} + +// 显示成长值详情弹窗 +function showGrowthDetail(detailId, type, detailData) { + const data = typeof detailData === 'string' ? JSON.parse(detailData) : detailData; + + let modalContent = ''; + + if (data.orderId) { + // 有关联订单的情况 + modalContent = ` +

订单详情

+
+
+ 订单编号: + ${data.orderId} +
+
+ 订单总金额: + ¥${(Math.random() * 1000 + 100).toFixed(2)} +
+
+ 订单时间: + ${data.time} +
+
+ 订单归属摊位: + ${['时尚服装店', '数码电子城', '美食餐厅', '家居生活馆'][Math.floor(Math.random() * 4)]} +
+
+ 成长值变化: + +${data.growth} +
+
+ `; + } else { + // 无关联订单的情况 + modalContent = ` +

成长值变化详情

+
+
+ 变化原因: + ${data.reason} +
+
+ 变化时间: + ${data.time} +
+
+ 成长值增加: + +${data.growth} +
+
+ ${getGrowthReasonDescription(data.type)} +
+
+ `; + } + + showDetailModal('成长值详情', modalContent); +} + +// 显示积分详情弹窗 +function showPointDetail(detailId, type, detailData) { + const data = typeof detailData === 'string' ? JSON.parse(detailData) : detailData; + + let modalContent = ''; + + if (data.orderId) { + // 有关联订单的情况 + modalContent = ` +

订单详情

+
+
+ 订单编号: + ${data.orderId} +
+
+ 订单总金额: + ¥${(Math.random() * 1000 + 100).toFixed(2)} +
+
+ 订单时间: + ${data.time} +
+
+ 订单归属摊位: + ${['时尚服装店', '数码电子城', '美食餐厅', '家居生活馆'][Math.floor(Math.random() * 4)]} +
+
+ 积分变化: + ${data.change > 0 ? '+' : ''}${data.change} +
+
+ ${data.change > 0 ? '订单消费获得积分奖励' : '使用积分抵扣订单金额'} +
+
+ `; + } else { + // 无关联订单的情况 + modalContent = ` +

积分变化详情

+
+
+ 变化原因: + ${data.reason} +
+
+ 变化时间: + ${data.time} +
+
+ 积分变化: + ${data.change > 0 ? '+' : ''}${data.change} +
+
+ ${getPointReasonDescription(data.type)} +
+
+ `; + } + + showDetailModal('积分详情', modalContent); +} + +// 显示通用详情弹窗 +function showDetailModal(title, content) { + const modalHtml = ` +
+
+
+

${title}

+ +
+ +
+ ${content} +
+ +
+ +
+
+
+ `; + + // 移除现有弹窗 + const existingModal = document.getElementById('detail-modal'); + if (existingModal) { + existingModal.remove(); + } + + document.body.insertAdjacentHTML('beforeend', modalHtml); +} + +// 关闭详情弹窗 +function closeDetailModal(event) { + if (event && event.target !== event.currentTarget) { + return; + } + + const modal = document.getElementById('detail-modal'); + if (modal) { + modal.remove(); + } +} + +// 获取成长值原因描述 +function getGrowthReasonDescription(type) { + const descriptions = { + 'register': '新用户注册时系统自动发放的奖励成长值', + 'birthday': '会员生日当天系统自动发放的生日礼品成长值', + 'activity': '参与平台活动获得的奖励成长值', + 'order': '订单消费根据消费金额按比例获得的成长值' + }; + + return descriptions[type] || '其他原因获得的成长值'; +} + +// 获取积分原因描述 +function getPointReasonDescription(type) { + const descriptions = { + 'register': '新用户注册时系统自动发放的奖励积分', + 'birthday': '会员生日当天系统自动发放的生日礼品积分', + 'activity': '参与平台活动获得的奖励积分', + 'order_earn': '订单消费根据消费金额按比例获得的积分奖励', + 'order_use': '在订单中使用积分抵扣部分金额' + }; + + return descriptions[type] || '其他原因的积分变化'; +} + +// 分页功能(成长值) +function growthPrevPage(memberId) { + showNotification('已到第一页', 'info'); +} + +function growthNextPage(memberId) { + showNotification('已到最后一页', 'info'); +} + +// 分页功能(积分) +function pointsPrevPage(memberId) { + showNotification('已到第一页', 'info'); +} + +function pointsNextPage(memberId) { + showNotification('已到最后一页', 'info'); +} + +// 导出函数 +window.memberTabManager = memberTabManager; +window.openLevelSettingsTab = openLevelSettingsTab; +window.openLevelDetailTab = openLevelDetailTab; +window.openLevelEditTab = openLevelEditTab; +window.openBatchLevelEditTab = openBatchLevelEditTab; +window.openCouponModal = openCouponModal; +window.testCouponModal = testCouponModal; +window.closeCouponModal = closeCouponModal; +window.resetCouponForm = resetCouponForm; +window.adjustThreshold = adjustThreshold; +window.adjustDiscount = adjustDiscount; +window.addCouponThreshold = addCouponThreshold; +window.submitCoupon = submitCoupon; +window.submitLevelDetail = submitLevelDetail; +window.submitLevelEdit = submitLevelEdit; +window.submitBatchLevelEdit = submitBatchLevelEdit; +window.toggleStallDropdown = toggleStallDropdown; +window.toggleBatchStallDropdown = toggleBatchStallDropdown; +window.updateBatchSelectedStalls = updateBatchSelectedStalls; +window.removeBatchSelectedStall = removeBatchSelectedStall; +window.removeSelectedStall = removeSelectedStall; +window.filterStallTable = filterStallTable; +window.openMemberListTab = openMemberListTab; +window.getLevelBadgeColor = getLevelBadgeColor; +window.initializeMemberListPagination = initializeMemberListPagination; +window.updatePaginationDisplay = updatePaginationDisplay; +window.goToPage = goToPage; +window.changePageSize = changePageSize; +window.filterMemberList = filterMemberList; +window.resetMemberFilters = resetMemberFilters; +window.toggleAllMembers = toggleAllMembers; +window.sortMemberTable = sortMemberTable; +window.viewMemberDetail = viewMemberDetail; +window.getMemberDataById = getMemberDataById; +window.openMemberDetailTab = openMemberDetailTab; +window.generateMemberCoupons = generateMemberCoupons; +window.generateGrowthDetails = generateGrowthDetails; +window.generatePointDetails = generatePointDetails; +window.switchDetailTab = switchDetailTab; +window.showMemberCouponsModal = showMemberCouponsModal; +window.closeMemberCouponsModal = closeMemberCouponsModal; +window.showGrowthDetail = showGrowthDetail; +window.showPointDetail = showPointDetail; +window.showDetailModal = showDetailModal; +window.closeDetailModal = closeDetailModal; +window.getGrowthReasonDescription = getGrowthReasonDescription; +window.getPointReasonDescription = getPointReasonDescription; +window.growthPrevPage = growthPrevPage; +window.growthNextPage = growthNextPage; +window.pointsPrevPage = pointsPrevPage; +window.pointsNextPage = pointsNextPage; \ No newline at end of file diff --git a/merchant/js/pages/coupon-marketing.js b/merchant/js/pages/coupon-marketing.js new file mode 100644 index 0000000..0746507 --- /dev/null +++ b/merchant/js/pages/coupon-marketing.js @@ -0,0 +1,6 @@ +// 优惠券营销工具管理页面的JavaScript逻辑 + +document.addEventListener('DOMContentLoaded', function() { + console.log('优惠券营销工具管理页面初始化完成'); + // 这里可以添加优惠券管理相关的功能 +}); \ No newline at end of file diff --git a/merchant/js/pages/data-center.js b/merchant/js/pages/data-center.js new file mode 100644 index 0000000..fedc3cf --- /dev/null +++ b/merchant/js/pages/data-center.js @@ -0,0 +1,6 @@ +// 数据中心页面的JavaScript逻辑 + +document.addEventListener('DOMContentLoaded', function() { + console.log('数据中心页面初始化完成'); + // 这里可以添加数据中心相关的功能 +}); \ No newline at end of file diff --git a/merchant/js/pages/level-detail.js b/merchant/js/pages/level-detail.js new file mode 100644 index 0000000..570dcc1 --- /dev/null +++ b/merchant/js/pages/level-detail.js @@ -0,0 +1,57 @@ +// 等级明细页面的JavaScript逻辑 + +let currentShopName = ''; + +// 获取URL参数 +function getUrlParameter(name) { + name = name.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]'); + const regex = new RegExp('[\\?&]' + name + '=([^&#]*)'); + const results = regex.exec(location.search); + return results === null ? '' : decodeURIComponent(results[1].replace(/\+/g, ' ')); +} + +// 页面初始化 +document.addEventListener('DOMContentLoaded', function() { + currentShopName = getUrlParameter('shop'); + if (currentShopName) { + document.getElementById('page-title').textContent = `${currentShopName} - 等级设置明细`; + loadLevelData(); + } +}); + +// 加载等级数据 +function loadLevelData() { + // 模拟等级数据 + const mockLevels = [ + { name: 'LV1', growth: 100, members: 1250, benefits: '9.5折优惠' }, + { name: 'LV2', growth: 500, members: 850, benefits: '9折优惠, 积分双倍' }, + { name: 'LV3', growth: 1200, members: 450, benefits: '8.5折优惠, 积分双倍, 生日优惠券' }, + { name: 'LV4', growth: 2500, members: 180, benefits: '8折优惠, 积分三倍, 生日优惠券, 专属客服' } + ]; + + const tableBody = document.getElementById('level-table-body'); + tableBody.innerHTML = mockLevels.map(level => ` + + ${level.name} + ${level.growth} + ${level.members} + ${level.benefits} + + `).join(''); +} + +// 打开等级编辑页面 +function openLevelEdit() { + const encodedShopName = encodeURIComponent(currentShopName); + window.location.href = `level-edit.html?shop=${encodedShopName}`; +} + +// 提交等级明细 +function submitLevelDetail() { + showNotification(`${currentShopName} 等级明细已提交`, 'success'); + console.log('提交等级明细:', currentShopName); +} + +// 导出函数 +window.openLevelEdit = openLevelEdit; +window.submitLevelDetail = submitLevelDetail; \ No newline at end of file diff --git a/merchant/js/pages/level-edit.js b/merchant/js/pages/level-edit.js new file mode 100644 index 0000000..f68d6c3 --- /dev/null +++ b/merchant/js/pages/level-edit.js @@ -0,0 +1,323 @@ +// 等级编辑页面的JavaScript逻辑 + +let currentShopName = ''; +let currentLevels = []; + +// 获取URL参数 +function getUrlParameter(name) { + name = name.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]'); + const regex = new RegExp('[\\?&]' + name + '=([^&#]*)'); + const results = regex.exec(location.search); + return results === null ? '' : decodeURIComponent(results[1].replace(/\+/g, ' ')); +} + +// 页面初始化 +document.addEventListener('DOMContentLoaded', function() { + currentShopName = getUrlParameter('shop'); + if (currentShopName) { + document.getElementById('page-title').textContent = `${currentShopName} - 等级编辑`; + loadLevelEditData(); + } +}); + +// 加载等级编辑数据 +function loadLevelEditData() { + // 模拟等级编辑数据 + currentLevels = [ + { + level: 'LV1', + name: '铜牌会员', + growthMin: 0, + growthMax: 100, + memberDiscount: true, + discountRate: 5, + pointExchange: false, + birthdayCoupon: false, + birthdayDoublePoints: false + }, + { + level: 'LV2', + name: '银牌会员', + growthMin: 101, + growthMax: 500, + memberDiscount: true, + discountRate: 10, + pointExchange: true, + birthdayCoupon: true, + birthdayDoublePoints: true + }, + { + level: 'LV3', + name: '金牌会员', + growthMin: 501, + growthMax: 1200, + memberDiscount: true, + discountRate: 15, + pointExchange: true, + birthdayCoupon: true, + birthdayDoublePoints: true + }, + { + level: 'LV4', + name: '钻石会员', + growthMin: 1201, + growthMax: 9999, + memberDiscount: true, + discountRate: 20, + pointExchange: true, + birthdayCoupon: true, + birthdayDoublePoints: true + } + ]; + + renderLevelEditTable(); +} + +// 渲染等级编辑表格 +function renderLevelEditTable() { + const tableBody = document.getElementById('level-edit-table-body'); + tableBody.innerHTML = currentLevels.map((level, index) => ` + + ${level.level} + + + + +
+ + - + +
+ + + + + + + + + + + + + + + + + + + + +
+ ${index === currentLevels.length - 1 ? ` + + ` : ''} + +
+ + + `).join(''); +} + +// 切换折扣率输入框状态 +function toggleDiscountRate(index) { + const checkbox = document.getElementById(`memberDiscount_${index}`); + const discountInput = document.getElementById(`discountRate_${index}`); + + if (checkbox && discountInput) { + if (checkbox.checked) { + discountInput.disabled = false; + discountInput.classList.remove('bg-gray-100'); + } else { + discountInput.disabled = true; + discountInput.classList.add('bg-gray-100'); + } + } +} + +// 切换优惠券按钮显示 +function toggleCouponButton(index) { + const checkbox = document.getElementById(`birthdayCoupon_${index}`); + const addButton = document.getElementById(`addCouponBtn_${index}`); + + if (checkbox && addButton) { + if (checkbox.checked) { + addButton.classList.remove('hidden'); + } else { + addButton.classList.add('hidden'); + } + } +} + +// 添加生日优惠券 +function addBirthdayCoupon(index) { + // 显示弹窗 + const modal = document.getElementById('coupon-modal'); + if (modal) { + modal.classList.remove('hidden'); + resetCouponForm(); + console.log('显示添加生日优惠券弹窗,等级索引:', index); + } +} + +// 关闭优惠券弹窗 +function closeCouponModal(event) { + // 如果点击的是弹窗背景,则关闭弹窗 + if (event && event.target !== event.currentTarget) { + return; + } + + const modal = document.getElementById('coupon-modal'); + if (modal) { + modal.classList.add('hidden'); + console.log('关闭优惠券弹窗'); + } +} + +// 重置优惠券表单 +function resetCouponForm() { + const form = document.getElementById('coupon-form'); + if (form) { + // 重置为默认值 + document.getElementById('coupon-name').value = '生日优惠券'; + document.getElementById('coupon-threshold').value = '10'; + document.getElementById('coupon-discount').value = '1'; + document.getElementById('coupon-validity').value = '1'; + } +} + +// 调整门槛金额 +function adjustThreshold(delta) { + const input = document.getElementById('coupon-threshold'); + if (input) { + const currentValue = parseInt(input.value) || 0; + const newValue = Math.max(0, currentValue + delta); + input.value = newValue; + } +} + +// 调整减免金额 +function adjustDiscount(delta) { + const input = document.getElementById('coupon-discount'); + if (input) { + const currentValue = parseInt(input.value) || 0; + const newValue = Math.max(0, currentValue + delta); + input.value = newValue; + } +} + +// 提交优惠券 +function submitCoupon() { + const form = document.getElementById('coupon-form'); + if (!form) return; + + // 获取表单数据 + const couponData = { + name: document.getElementById('coupon-name').value, + threshold: document.getElementById('coupon-threshold').value, + discount: document.getElementById('coupon-discount').value, + validity: document.getElementById('coupon-validity').value + }; + + // 验证表单 + if (!couponData.name.trim()) { + showNotification('请输入优惠券名称', 'error'); + return; + } + + if (!couponData.threshold || couponData.threshold < 0) { + showNotification('请输入有效的门槛金额', 'error'); + return; + } + + if (!couponData.discount || couponData.discount < 0) { + showNotification('请输入有效的减免金额', 'error'); + return; + } + + if (parseInt(couponData.discount) >= parseInt(couponData.threshold)) { + showNotification('减免金额不能大于或等于门槛金额', 'error'); + return; + } + + // 提交成功 + console.log('提交优惠券数据:', couponData); + showNotification(`成功添加优惠券:${couponData.name}`, 'success'); + + // 关闭弹窗 + closeCouponModal(); +} + +// 删除等级行 +function deleteLevel(index) { + if (currentLevels.length <= 1) { + showNotification('至少需要保留一个等级', 'warning'); + return; + } + + currentLevels.splice(index, 1); + + // 重新编号等级 + currentLevels.forEach((level, i) => { + level.level = `LV${i + 1}`; + }); + + renderLevelEditTable(); + showNotification(`删除等级 ${index + 1}`, 'success'); + console.log('删除等级:', index); +} + +// 添加新等级 +function addNewLevel() { + const newLevelNum = currentLevels.length + 1; + const lastLevel = currentLevels[currentLevels.length - 1]; + + const newLevel = { + level: `LV${newLevelNum}`, + name: `${getLevelName(newLevelNum)}会员`, + growthMin: lastLevel.growthMax + 1, + growthMax: lastLevel.growthMax + 1000, + memberDiscount: true, + discountRate: Math.min(lastLevel.discountRate + 5, 50), + pointExchange: true, + birthdayCoupon: true, + birthdayDoublePoints: true + }; + + currentLevels.push(newLevel); + renderLevelEditTable(); + showNotification(`添加新等级 LV${newLevelNum}`, 'success'); + console.log('添加新等级:', newLevel); +} + +// 获取等级名称 +function getLevelName(levelNum) { + const names = ['铜牌', '银牌', '金牌', '钻石', '黑钻', '至尊', '王者', '传奇']; + return names[levelNum - 1] || `LV${levelNum}`; +} + +// 提交等级编辑 +function submitLevelEdit() { + showNotification(`${currentShopName} 等级编辑已提交`, 'success'); + console.log('提交等级编辑:', currentShopName); +} + +// 导出函数 +window.toggleDiscountRate = toggleDiscountRate; +window.toggleCouponButton = toggleCouponButton; +window.addBirthdayCoupon = addBirthdayCoupon; +window.closeCouponModal = closeCouponModal; +window.resetCouponForm = resetCouponForm; +window.adjustThreshold = adjustThreshold; +window.adjustDiscount = adjustDiscount; +window.addCouponThreshold = addCouponThreshold; +window.submitCoupon = submitCoupon; +window.deleteLevel = deleteLevel; +window.addNewLevel = addNewLevel; +window.submitLevelEdit = submitLevelEdit; \ No newline at end of file diff --git a/merchant/js/pages/level-settings.js b/merchant/js/pages/level-settings.js new file mode 100644 index 0000000..3317842 --- /dev/null +++ b/merchant/js/pages/level-settings.js @@ -0,0 +1,308 @@ +// 等级设置页面的Tab系统JavaScript逻辑 + +// 初始化页面 +document.addEventListener('DOMContentLoaded', function() { + initializeSidebar(); + initializeSidebarSearch(); + // 默认打开等级设置Tab + openLevelSettingsTab(); +}); + +// 打开等级设置Tab(从member-tabs.js调用) +function openLevelSettingsTab() { + if (typeof memberTabManager !== 'undefined') { + memberTabManager.showDefaultContent(); + // 创建等级设置tab + const content = generateLevelSettingsContent(); + memberTabManager.createTab('level-settings', '等级设置', content, false); + } +} + +// 生成等级设置表格内容 +function generateLevelSettingsContent() { + return ` +
+
+

等级设置

+
+ + +
+
+ +
+ + +
+
+
+
+ + +
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ 摊位名称 + + 是否启用会员 + + 会员等级 + + 操作 +
时尚服装店 + + lv1, lv2, lv3, lv4 + +
数码电子城 + + lv1, lv2, lv3 + +
美食餐厅 + + lv1, lv2, lv3, lv4 + +
家居生活馆 + + lv1, lv2 + +
运动健身店 + + lv1, lv2, lv3, lv4 + +
+
+
+ `; +} + +// 摊位筛选相关功能 +let selectedStalls = []; +let dropdownOpen = false; + +function toggleStallDropdown() { + const dropdown = document.getElementById('stall-dropdown-list'); + const button = document.getElementById('stall-dropdown-btn'); + + if (dropdown && button) { + dropdownOpen = !dropdownOpen; + if (dropdownOpen) { + dropdown.classList.remove('hidden'); + // 添加点击外部关闭功能 + setTimeout(() => { + document.addEventListener('click', closeDropdownOnClickOutside); + }, 0); + } else { + dropdown.classList.add('hidden'); + document.removeEventListener('click', closeDropdownOnClickOutside); + } + } +} + +function closeDropdownOnClickOutside(event) { + const dropdown = document.getElementById('stall-dropdown-list'); + const button = document.getElementById('stall-dropdown-btn'); + + if (dropdown && button && !dropdown.contains(event.target) && !button.contains(event.target)) { + dropdown.classList.add('hidden'); + dropdownOpen = false; + document.removeEventListener('click', closeDropdownOnClickOutside); + } +} + +function updateSelectedStalls() { + const checkboxes = document.querySelectorAll('#stall-dropdown-list input[type="checkbox"]'); + selectedStalls = []; + + checkboxes.forEach(checkbox => { + if (checkbox.checked) { + selectedStalls.push(checkbox.value); + } + }); + + updateDropdownText(); + updateSelectedStallsDisplay(); +} + +function updateDropdownText() { + const dropdownText = document.getElementById('dropdown-text'); + if (dropdownText) { + if (selectedStalls.length === 0) { + dropdownText.textContent = '请选择摊位名称...'; + } else if (selectedStalls.length === 1) { + dropdownText.textContent = selectedStalls[0]; + } else { + dropdownText.textContent = `已选择 ${selectedStalls.length} 个摊位`; + } + } +} + +function updateSelectedStallsDisplay() { + const selectedDiv = document.getElementById('selected-stalls'); + if (!selectedDiv) return; + + selectedDiv.innerHTML = ''; + + selectedStalls.forEach(stall => { + const tag = document.createElement('span'); + tag.className = 'inline-flex items-center px-2 py-1 rounded-md text-xs font-medium bg-green-100 text-green-800'; + tag.innerHTML = ` + ${stall} + + `; + selectedDiv.appendChild(tag); + }); +} + +function removeSelectedStall(stallName) { + selectedStalls = selectedStalls.filter(stall => stall !== stallName); + + // 更新checkbox状态 + const checkboxes = document.querySelectorAll('#stall-dropdown-list input[type="checkbox"]'); + checkboxes.forEach(checkbox => { + if (checkbox.value === stallName) { + checkbox.checked = false; + } + }); + + updateDropdownText(); + updateSelectedStallsDisplay(); +} + +function filterStallTable() { + const tableRows = document.querySelectorAll('#tab-content-area tbody tr'); + + if (selectedStalls.length === 0) { + // 如果没有选择任何摊位,显示所有行 + tableRows.forEach(row => { + row.style.display = ''; + }); + showNotification('已显示所有摊位', 'info'); + } else { + // 根据选择的摊位筛选表格行 + let visibleCount = 0; + tableRows.forEach(row => { + const stallNameCell = row.querySelector('td:first-child'); + if (stallNameCell) { + const stallName = stallNameCell.textContent.trim(); + if (selectedStalls.includes(stallName)) { + row.style.display = ''; + visibleCount++; + } else { + row.style.display = 'none'; + } + } + }); + showNotification(`已筛选显示 ${visibleCount} 个摊位`, 'success'); + } +} + +// 导出函数 +window.openLevelSettingsTab = openLevelSettingsTab; +window.generateLevelSettingsContent = generateLevelSettingsContent; +window.openBatchLevelEditTab = openBatchLevelEditTab; +window.toggleStallDropdown = toggleStallDropdown; +window.updateSelectedStalls = updateSelectedStalls; +window.removeSelectedStall = removeSelectedStall; +window.filterStallTable = filterStallTable; \ No newline at end of file diff --git a/merchant/js/sidebar.js b/merchant/js/sidebar.js new file mode 100644 index 0000000..6159dc4 --- /dev/null +++ b/merchant/js/sidebar.js @@ -0,0 +1,179 @@ +// 通用侧边栏组件的JavaScript逻辑 + +// 全局状态管理 +let currentExpandedMenus = []; + +// 获取当前页面路径信息 +function getCurrentPageInfo() { + const path = window.location.pathname; + const filename = path.split('/').pop(); + + // 根据文件名判断当前页面 + if (filename === 'index.html' || path.endsWith('/')) { + return { section: 'home', page: 'home' }; + } else if (filename === 'data-center.html') { + return { section: 'data-center', page: 'data-center' }; + } else if (filename === 'coupon-marketing.html') { + return { section: 'coupon-marketing', page: 'coupon-marketing' }; + } else if (path.includes('/member/')) { + if (filename === 'level-settings.html') { + return { section: 'member', page: 'level-settings' }; + } else if (filename === 'level-detail.html') { + return { section: 'member', page: 'level-detail' }; + } else if (filename === 'level-edit.html') { + return { section: 'member', page: 'level-edit' }; + } + return { section: 'member', page: 'unknown' }; + } + + return { section: 'unknown', page: 'unknown' }; +} + +// 菜单展开/收起功能 +function toggleMenu(menuId) { + const arrow = document.getElementById(menuId + '-arrow'); + const submenu = document.getElementById(menuId + '-submenu'); + + if (currentExpandedMenus.includes(menuId)) { + // 收起菜单 + currentExpandedMenus = currentExpandedMenus.filter(id => id !== menuId); + + if (arrow) { + arrow.classList.remove('rotate-180'); + } + + if (submenu) { + submenu.classList.add('hidden'); + } + } else { + // 展开菜单 + currentExpandedMenus.push(menuId); + + if (arrow) { + arrow.classList.add('rotate-180'); + } + + if (submenu) { + submenu.classList.remove('hidden'); + submenu.classList.add('fade-in'); + } + } + + console.log('菜单状态更新:', menuId, currentExpandedMenus); +} + +// 初始化菜单状态 +function initializeSidebar() { + const currentPage = getCurrentPageInfo(); + + // 根据当前页面设置菜单状态 + if (currentPage.section === 'member') { + // 会员管理菜单默认展开 + if (!currentExpandedMenus.includes('member')) { + toggleMenu('member'); + } + + // 设置当前页面高亮 + highlightCurrentMenu(currentPage); + } else if (currentPage.section === 'home') { + // 主页高亮 + highlightCurrentMenu(currentPage); + // 会员管理菜单默认展开 + if (!currentExpandedMenus.includes('member')) { + toggleMenu('member'); + } + } else { + // 其他页面高亮对应菜单 + highlightCurrentMenu(currentPage); + } + + console.log('侧边栏初始化完成,当前页面:', currentPage); +} + +// 高亮当前菜单项 +function highlightCurrentMenu(pageInfo) { + // 清除所有高亮状态 + document.querySelectorAll('.menu-item').forEach(item => { + item.classList.remove('text-blue-500'); + item.classList.add('text-gray-700'); + }); + + // 根据页面信息高亮对应菜单 + let targetElement = null; + + if (pageInfo.section === 'home') { + targetElement = document.querySelector('[data-menu="home"]'); + } else if (pageInfo.section === 'data-center') { + targetElement = document.querySelector('[data-menu="data-center"]'); + } else if (pageInfo.section === 'coupon-marketing') { + targetElement = document.querySelector('[data-menu="coupon-marketing"]'); + } else if (pageInfo.section === 'member') { + if (pageInfo.page === 'level-settings' || pageInfo.page === 'level-detail' || pageInfo.page === 'level-edit') { + targetElement = document.querySelector('[data-menu="level-settings"]'); + } + } + + if (targetElement) { + targetElement.classList.remove('text-gray-700', 'text-gray-600'); + targetElement.classList.add('text-blue-500'); + } +} + +// 搜索功能 +function initializeSidebarSearch() { + const searchInput = document.querySelector('input[placeholder*="搜索"]'); + if (searchInput) { + searchInput.addEventListener('input', function(e) { + const searchTerm = e.target.value.toLowerCase(); + filterMenuItems(searchTerm); + }); + } +} + +// 过滤菜单项 +function filterMenuItems(searchTerm) { + const menuItems = document.querySelectorAll('nav div'); + + menuItems.forEach(item => { + const text = item.textContent.toLowerCase(); + if (text.includes(searchTerm) || searchTerm === '') { + item.style.display = ''; + } else { + item.style.display = 'none'; + } + }); + + console.log('搜索筛选:', searchTerm); +} + +// 页面跳转函数 +function navigateToPage(url) { + window.location.href = url; +} + +// 获取相对路径 +function getRelativePath(targetPath) { + const currentPath = window.location.pathname; + const currentDir = currentPath.substring(0, currentPath.lastIndexOf('/')); + + // 判断当前是否在子目录中 + if (currentDir.includes('/pages')) { + if (currentDir.includes('/member')) { + // 在 member 子目录中 + return targetPath.startsWith('../../') ? targetPath : '../../' + targetPath; + } else { + // 在 pages 目录中 + return targetPath.startsWith('../') ? targetPath : '../' + targetPath; + } + } + + // 在根目录中 + return targetPath; +} + +// 导出函数 +window.toggleMenu = toggleMenu; +window.initializeSidebar = initializeSidebar; +window.initializeSidebarSearch = initializeSidebarSearch; +window.navigateToPage = navigateToPage; +window.getRelativePath = getRelativePath; \ No newline at end of file diff --git a/merchant/pages/coupon-marketing.html b/merchant/pages/coupon-marketing.html new file mode 100644 index 0000000..018884d --- /dev/null +++ b/merchant/pages/coupon-marketing.html @@ -0,0 +1,213 @@ + + + + + + 大数集市商户端 - 优惠券营销工具管理 + + + +
+ +
+
+ +

大数集市商户端

+
+ +
+ + + + +
+ 用户 +
+
+
+ +
+ + + + +
+
+
+
+ + + +

优惠券营销工具管理

+

优惠券管理功能开发中...

+
+
+
+
+
+
+ + + + + + + \ No newline at end of file diff --git a/merchant/pages/data-center.html b/merchant/pages/data-center.html new file mode 100644 index 0000000..2fd937c --- /dev/null +++ b/merchant/pages/data-center.html @@ -0,0 +1,216 @@ + + + + + + 大数集市商户端 - 数据中心 + + + +
+ +
+
+ +

大数集市商户端

+
+ +
+ + + + +
+ 用户 +
+
+
+ +
+ + + + +
+
+
+
+ + + + + + +

数据中心

+

数据分析功能开发中...

+
+
+
+
+
+
+ + + + + + + \ No newline at end of file diff --git a/merchant/pages/member/level-detail.html b/merchant/pages/member/level-detail.html new file mode 100644 index 0000000..a2504a4 --- /dev/null +++ b/merchant/pages/member/level-detail.html @@ -0,0 +1,231 @@ + + + + + + 大数集市商户端 - 等级明细 + + + +
+ +
+
+ +

大数集市商户端

+
+ +
+ + + + +
+ 用户 +
+
+
+ +
+ + + + +
+
+
+

等级设置明细

+
+ + +
+
+ +
+ + + + + + + + + + + + +
等级名称所需成长值会员人数会员权益
+
+
+
+
+
+ + + + + + + \ No newline at end of file diff --git a/merchant/pages/member/level-edit.html b/merchant/pages/member/level-edit.html new file mode 100644 index 0000000..58aea2e --- /dev/null +++ b/merchant/pages/member/level-edit.html @@ -0,0 +1,336 @@ + + + + + + 大数集市商户端 - 等级编辑 + + + +
+ +
+
+ +

大数集市商户端

+
+ +
+ + + + +
+ 用户 +
+
+
+ +
+ + + + +
+
+
+

等级编辑

+
+ + +
+
+ +
+ + + + + + + + + + + + + + + + + + +
等级等级名称成长值范围开启会员折扣折扣率(%)开启积分兑换开启生日优惠券生日优惠券操作开启生日双倍积分操作
+
+
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/merchant/pages/member/level-settings.html b/merchant/pages/member/level-settings.html new file mode 100644 index 0000000..0e9b47b --- /dev/null +++ b/merchant/pages/member/level-settings.html @@ -0,0 +1,310 @@ + + + + + + 大数集市商户端 - 等级设置 + + + +
+ +
+
+ +

大数集市商户端

+
+ +
+ + + + +
+ 用户 +
+
+
+ +
+ + + + +
+ +
+ +
+
+ +
+
+ + +
+ +
+
+
+
+
+ + + + + + + + + + \ No newline at end of file