feat: 积分商城兑换记录、次卡管理、满赠/第二份半价、营销日历
- 积分商城: 新增兑换记录tab、到账通知、核销抽屉、商品类型标签 - 次卡管理: 新页面,支持完全免费/金额上限两种模式,4种适用范围 - 满减活动: 扩展支持满赠(买X赠Y)和第二份半价,抽屉联动切换 - 营销日历: 甘特图总览所有活动,冲突提示,类型图例 - 会员管理: 动态等级、开关式权益配置(上次遗留同步提交)
This commit is contained in:
@@ -646,11 +646,13 @@
|
||||
<i data-lucide="chevron-right" class="menu-arrow"></i>
|
||||
</div>
|
||||
<div class="menu-sub" id="menu-marketing">
|
||||
<div class="menu-item" data-tab="营销日历" onclick="switchTab(this, '营销日历')"><span class="menu-label">营销日历</span></div>
|
||||
<div class="menu-item" data-tab="优惠券" onclick="switchTab(this, '优惠券')"><span class="menu-label">优惠券</span></div>
|
||||
<div class="menu-item" data-tab="满减活动" onclick="switchTab(this, '满减活动')"><span class="menu-label">满减活动</span></div>
|
||||
<div class="menu-item" data-tab="限时折扣" onclick="switchTab(this, '限时折扣')"><span class="menu-label">限时折扣</span></div>
|
||||
<div class="menu-item" data-tab="秒杀活动" onclick="switchTab(this, '秒杀活动')"><span class="menu-label">秒杀活动</span></div>
|
||||
<div class="menu-item" data-tab="新客有礼" onclick="switchTab(this, '新客有礼')"><span class="menu-label">新客有礼</span></div>
|
||||
<div class="menu-item" data-tab="次卡管理" onclick="switchTab(this, '次卡管理')"><span class="menu-label">次卡管理</span></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1180,6 +1182,8 @@
|
||||
'限时折扣': 'pages/mkt-flash-sale.html',
|
||||
'秒杀活动': 'pages/mkt-seckill.html',
|
||||
'新客有礼': 'pages/mkt-new-customer.html',
|
||||
'次卡管理': 'pages/mkt-pass-card.html',
|
||||
'营销日历': 'pages/mkt-calendar.html',
|
||||
'会员管理': 'pages/mbr-members.html',
|
||||
'储值卡': 'pages/mbr-prepaid.html',
|
||||
'积分商城': 'pages/mbr-points.html',
|
||||
|
||||
@@ -16,15 +16,20 @@
|
||||
.mm-avatar { width:34px; height:34px; border-radius:50%; display:flex; align-items:center; justify-content:center; color:#fff; font-size:13px; font-weight:600; flex-shrink:0; }
|
||||
|
||||
/* 等级体系 Tab */
|
||||
.mm-level-grid { display:grid; grid-template-columns:repeat(4,1fr); gap:16px; margin-bottom:24px; }
|
||||
.mm-level-card { background:#fff; border-radius:10px; padding:24px 20px; box-shadow:var(--g-shadow-sm); border:1px solid var(--g-border); transition:all var(--g-transition); display:flex; flex-direction:column; align-items:center; text-align:center; }
|
||||
.mm-level-card:hover { box-shadow:var(--g-shadow-md); transform:translateY(-1px); }
|
||||
.mm-level-icon { width:56px; height:56px; border-radius:50%; display:flex; align-items:center; justify-content:center; margin-bottom:12px; }
|
||||
.mm-level-name { font-size:16px; font-weight:600; color:var(--g-text); margin-bottom:4px; }
|
||||
.mm-level-cond { font-size:12px; color:var(--g-text-muted); margin-bottom:14px; padding:3px 10px; background:var(--g-bg-subtle); border-radius:10px; }
|
||||
.mm-level-perks { width:100%; text-align:left; margin-bottom:16px; }
|
||||
.mm-level-perk { display:flex; align-items:center; gap:6px; font-size:13px; color:var(--g-text-secondary); padding:5px 0; }
|
||||
.mm-level-grid { display:flex; flex-direction:column; gap:12px; margin-bottom:24px; }
|
||||
.mm-level-card { background:#fff; border-radius:10px; padding:18px 20px; box-shadow:var(--g-shadow-sm); border:1px solid var(--g-border); transition:all var(--g-transition); display:flex; align-items:center; gap:16px; }
|
||||
.mm-level-card:hover { box-shadow:var(--g-shadow-md); }
|
||||
.mm-level-icon { width:48px; height:48px; border-radius:50%; display:flex; align-items:center; justify-content:center; flex-shrink:0; }
|
||||
.mm-level-name { font-size:15px; font-weight:600; color:var(--g-text); }
|
||||
.mm-level-cond { font-size:12px; color:var(--g-text-muted); margin-top:2px; }
|
||||
.mm-level-perks { display:flex; gap:8px; flex-wrap:wrap; margin-top:6px; }
|
||||
.mm-level-perk { display:inline-flex; align-items:center; gap:4px; font-size:12px; color:var(--g-text-secondary); padding:2px 8px; background:#f8f9fb; border-radius:4px; }
|
||||
.mm-level-perk i { color:var(--g-success); flex-shrink:0; }
|
||||
.mm-level-info { flex:1; min-width:0; }
|
||||
.mm-level-actions { display:flex; gap:8px; flex-shrink:0; }
|
||||
.mm-level-order { font-size:20px; font-weight:700; color:var(--g-text-muted); width:28px; text-align:center; flex-shrink:0; }
|
||||
.mm-add-level-btn { width:100%; height:44px; border:1px dashed #d9d9d9; border-radius:10px; background:#fff; color:var(--g-text-muted); font-size:13px; cursor:pointer; display:flex; align-items:center; justify-content:center; gap:6px; transition:var(--g-transition); }
|
||||
.mm-add-level-btn:hover { border-color:var(--primary); color:var(--primary); }
|
||||
|
||||
.mm-section-hd { font-size:15px; font-weight:600; color:var(--g-text); padding-left:10px; border-left:3px solid var(--primary); margin-bottom:16px; }
|
||||
.mm-day-card { background:#fff; border-radius:10px; padding:20px 24px; box-shadow:var(--g-shadow-sm); border:1px solid var(--g-border); }
|
||||
@@ -45,6 +50,31 @@
|
||||
.mm-mini-table th { text-align:left; padding:8px 10px; background:var(--g-bg-subtle); color:var(--g-text-muted); font-weight:500; font-size:11px; }
|
||||
.mm-mini-table td { padding:8px 10px; border-bottom:1px solid #f5f5f5; color:var(--g-text); }
|
||||
.mm-tag-list { display:flex; gap:6px; flex-wrap:wrap; margin-top:10px; }
|
||||
.mm-tag-add { display:inline-flex; align-items:center; gap:4px; padding:5px 12px; border-radius:16px; border:1px dashed #d9d9d9; font-size:12px; cursor:pointer; color:var(--g-text-muted); transition:var(--g-transition); background:none; }
|
||||
.mm-tag-add:hover { border-color:var(--primary); color:var(--primary); }
|
||||
.mm-tag-input { width:80px; height:26px; padding:0 8px; border:1px solid var(--primary); border-radius:16px; font-size:12px; outline:none; }
|
||||
.mm-tag-remove { margin-left:2px; cursor:pointer; color:var(--g-text-muted); display:inline-flex; align-items:center; transition:var(--g-transition); }
|
||||
.mm-tag-remove:hover { color:var(--g-danger); }
|
||||
|
||||
/* 等级编辑抽屉 */
|
||||
.mm-perk-row { display:flex; align-items:center; gap:8px; margin-bottom:8px; }
|
||||
.mm-perk-row input { flex:1; }
|
||||
.mm-perk-remove { background:none; border:none; color:var(--g-text-muted); cursor:pointer; display:flex; align-items:center; justify-content:center; width:24px; height:24px; border-radius:6px; transition:var(--g-transition); }
|
||||
.mm-perk-remove:hover { color:var(--g-danger); background:#fef2f2; }
|
||||
.mm-add-perk { color:var(--primary); font-size:12px; cursor:pointer; background:none; border:none; padding:0; display:flex; align-items:center; gap:4px; transition:var(--g-transition); }
|
||||
.mm-add-perk:hover { text-decoration:underline; }
|
||||
.mm-upgrade-section { background:#f8f9fb; border-radius:8px; padding:14px; margin-bottom:12px; }
|
||||
.mm-upgrade-row { display:flex; align-items:center; gap:8px; font-size:13px; color:var(--g-text-secondary); }
|
||||
.mm-perk-card { background:#f8f9fb; border-radius:8px; padding:12px 14px; margin-bottom:10px; border:1px solid #f0f0f0; }
|
||||
.mm-perk-card-hd { display:flex; align-items:center; gap:10px; }
|
||||
.mm-perk-card-hd .mm-perk-label { flex:1; font-size:13px; font-weight:500; color:var(--g-text); }
|
||||
.mm-perk-card-bd { margin-top:10px; padding-top:10px; border-top:1px solid #eee; display:flex; align-items:center; gap:8px; flex-wrap:wrap; font-size:13px; color:var(--g-text-secondary); }
|
||||
.mm-perk-card-bd.hidden { display:none; }
|
||||
.mm-coupon-mini { display:flex; align-items:center; gap:6px; padding:4px 10px; background:#fff; border:1px solid #e5e7eb; border-radius:6px; font-size:12px; }
|
||||
.mm-coupon-mini-remove { cursor:pointer; color:var(--g-text-muted); display:inline-flex; align-items:center; transition:var(--g-transition); }
|
||||
.mm-coupon-mini-remove:hover { color:var(--g-danger); }
|
||||
.mm-add-coupon-link { color:var(--primary); font-size:12px; cursor:pointer; background:none; border:none; padding:0; display:inline-flex; align-items:center; gap:3px; }
|
||||
.mm-add-coupon-link:hover { text-decoration:underline; }
|
||||
</style>
|
||||
|
||||
<div>
|
||||
@@ -226,66 +256,91 @@
|
||||
<!-- ==================== TAB 2: 等级体系 ==================== -->
|
||||
<div id="mmTabLevels" style="display:none;">
|
||||
<div class="mm-section-hd">会员等级</div>
|
||||
<div class="mm-level-grid">
|
||||
<!-- 普通 -->
|
||||
<div class="mm-level-grid" id="mmLevelList">
|
||||
<!-- Lv1 普通 -->
|
||||
<div class="mm-level-card">
|
||||
<div class="mm-level-order">1</div>
|
||||
<div class="mm-level-icon" style="background:#f5f5f5;color:#999;">
|
||||
<i data-lucide="user" style="width:28px;height:28px;"></i>
|
||||
<i data-lucide="user" style="width:24px;height:24px;"></i>
|
||||
</div>
|
||||
<div class="mm-level-name">普通会员</div>
|
||||
<div class="mm-level-cond">注册即享</div>
|
||||
<div class="mm-level-perks">
|
||||
<div class="mm-level-perk"><i data-lucide="check" style="width:14px;height:14px;"></i>积分累计</div>
|
||||
<div class="mm-level-perk"><i data-lucide="check" style="width:14px;height:14px;"></i>会员价商品</div>
|
||||
<div class="mm-level-info">
|
||||
<div class="mm-level-name">普通会员</div>
|
||||
<div class="mm-level-cond">注册即享</div>
|
||||
<div class="mm-level-perks">
|
||||
<span class="mm-level-perk"><i data-lucide="check" style="width:12px;height:12px;"></i>积分累计</span>
|
||||
<span class="mm-level-perk"><i data-lucide="check" style="width:12px;height:12px;"></i>会员价商品</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mm-level-actions">
|
||||
<button class="g-btn g-btn-sm" onclick="openMmLevelDrawer('普通会员')">编辑</button>
|
||||
</div>
|
||||
<button class="g-btn g-btn-sm" style="width:100%;">编辑</button>
|
||||
</div>
|
||||
<!-- 银卡 -->
|
||||
<!-- Lv2 银卡 -->
|
||||
<div class="mm-level-card">
|
||||
<div class="mm-level-order">2</div>
|
||||
<div class="mm-level-icon" style="background:#e6f7ff;color:#1890ff;">
|
||||
<i data-lucide="award" style="width:28px;height:28px;"></i>
|
||||
<i data-lucide="award" style="width:24px;height:24px;"></i>
|
||||
</div>
|
||||
<div class="mm-level-name" style="color:#1890ff;">银卡会员</div>
|
||||
<div class="mm-level-cond">累计消费满 ¥500</div>
|
||||
<div class="mm-level-perks">
|
||||
<div class="mm-level-perk"><i data-lucide="check" style="width:14px;height:14px;"></i>全场9.8折</div>
|
||||
<div class="mm-level-perk"><i data-lucide="check" style="width:14px;height:14px;"></i>生日专属券</div>
|
||||
<div class="mm-level-perk"><i data-lucide="check" style="width:14px;height:14px;"></i>积分1.2倍</div>
|
||||
<div class="mm-level-info">
|
||||
<div class="mm-level-name" style="color:#1890ff;">银卡会员</div>
|
||||
<div class="mm-level-cond">累计消费满 ¥500</div>
|
||||
<div class="mm-level-perks">
|
||||
<span class="mm-level-perk"><i data-lucide="check" style="width:12px;height:12px;"></i>全场9.8折</span>
|
||||
<span class="mm-level-perk"><i data-lucide="check" style="width:12px;height:12px;"></i>生日赠券</span>
|
||||
<span class="mm-level-perk"><i data-lucide="check" style="width:12px;height:12px;"></i>积分1.2倍</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mm-level-actions">
|
||||
<button class="g-btn g-btn-sm" onclick="openMmLevelDrawer('银卡会员')">编辑</button>
|
||||
<button class="g-btn g-btn-sm" style="color:var(--g-danger);border-color:var(--g-danger);" onclick="this.closest('.mm-level-card').remove()"><i data-lucide="trash-2" style="width:13px;height:13px;"></i></button>
|
||||
</div>
|
||||
<button class="g-btn g-btn-sm" style="width:100%;">编辑</button>
|
||||
</div>
|
||||
<!-- 金卡 -->
|
||||
<!-- Lv3 金卡 -->
|
||||
<div class="mm-level-card">
|
||||
<div class="mm-level-order">3</div>
|
||||
<div class="mm-level-icon" style="background:#fff7e6;color:#fa8c16;">
|
||||
<i data-lucide="trophy" style="width:28px;height:28px;"></i>
|
||||
<i data-lucide="trophy" style="width:24px;height:24px;"></i>
|
||||
</div>
|
||||
<div class="mm-level-name" style="color:#fa8c16;">金卡会员</div>
|
||||
<div class="mm-level-cond">累计消费满 ¥2,000</div>
|
||||
<div class="mm-level-perks">
|
||||
<div class="mm-level-perk"><i data-lucide="check" style="width:14px;height:14px;"></i>全场9.5折</div>
|
||||
<div class="mm-level-perk"><i data-lucide="check" style="width:14px;height:14px;"></i>生日双倍积分</div>
|
||||
<div class="mm-level-perk"><i data-lucide="check" style="width:14px;height:14px;"></i>每月专属优惠券</div>
|
||||
<div class="mm-level-perk"><i data-lucide="check" style="width:14px;height:14px;"></i>积分1.5倍</div>
|
||||
<div class="mm-level-info">
|
||||
<div class="mm-level-name" style="color:#fa8c16;">金卡会员</div>
|
||||
<div class="mm-level-cond">累计消费满 ¥2,000</div>
|
||||
<div class="mm-level-perks">
|
||||
<span class="mm-level-perk"><i data-lucide="check" style="width:12px;height:12px;"></i>全场9.5折</span>
|
||||
<span class="mm-level-perk"><i data-lucide="check" style="width:12px;height:12px;"></i>生日双倍积分</span>
|
||||
<span class="mm-level-perk"><i data-lucide="check" style="width:12px;height:12px;"></i>每月赠券</span>
|
||||
<span class="mm-level-perk"><i data-lucide="check" style="width:12px;height:12px;"></i>积分1.5倍</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mm-level-actions">
|
||||
<button class="g-btn g-btn-sm" onclick="openMmLevelDrawer('金卡会员')">编辑</button>
|
||||
<button class="g-btn g-btn-sm" style="color:var(--g-danger);border-color:var(--g-danger);" onclick="this.closest('.mm-level-card').remove()"><i data-lucide="trash-2" style="width:13px;height:13px;"></i></button>
|
||||
</div>
|
||||
<button class="g-btn g-btn-sm" style="width:100%;">编辑</button>
|
||||
</div>
|
||||
<!-- 钻石 -->
|
||||
<!-- Lv4 钻石 -->
|
||||
<div class="mm-level-card">
|
||||
<div class="mm-level-order">4</div>
|
||||
<div class="mm-level-icon" style="background:#f9f0ff;color:#722ed1;">
|
||||
<i data-lucide="gem" style="width:28px;height:28px;"></i>
|
||||
<i data-lucide="gem" style="width:24px;height:24px;"></i>
|
||||
</div>
|
||||
<div class="mm-level-name" style="color:#722ed1;">钻石会员</div>
|
||||
<div class="mm-level-cond">累计消费满 ¥5,000</div>
|
||||
<div class="mm-level-perks">
|
||||
<div class="mm-level-perk"><i data-lucide="check" style="width:14px;height:14px;"></i>全场9折</div>
|
||||
<div class="mm-level-perk"><i data-lucide="check" style="width:14px;height:14px;"></i>生日礼品</div>
|
||||
<div class="mm-level-perk"><i data-lucide="check" style="width:14px;height:14px;"></i>专属客服</div>
|
||||
<div class="mm-level-perk"><i data-lucide="check" style="width:14px;height:14px;"></i>优先配送</div>
|
||||
<div class="mm-level-perk"><i data-lucide="check" style="width:14px;height:14px;"></i>积分2倍</div>
|
||||
<div class="mm-level-info">
|
||||
<div class="mm-level-name" style="color:#722ed1;">钻石会员</div>
|
||||
<div class="mm-level-cond">累计消费满 ¥5,000</div>
|
||||
<div class="mm-level-perks">
|
||||
<span class="mm-level-perk"><i data-lucide="check" style="width:12px;height:12px;"></i>全场9折</span>
|
||||
<span class="mm-level-perk"><i data-lucide="check" style="width:12px;height:12px;"></i>生日赠券+双倍积分</span>
|
||||
<span class="mm-level-perk"><i data-lucide="check" style="width:12px;height:12px;"></i>每月赠券</span>
|
||||
<span class="mm-level-perk"><i data-lucide="check" style="width:12px;height:12px;"></i>免配送费</span>
|
||||
<span class="mm-level-perk"><i data-lucide="check" style="width:12px;height:12px;"></i>优先配送</span>
|
||||
<span class="mm-level-perk"><i data-lucide="check" style="width:12px;height:12px;"></i>积分2倍</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mm-level-actions">
|
||||
<button class="g-btn g-btn-sm" onclick="openMmLevelDrawer('钻石会员')">编辑</button>
|
||||
<button class="g-btn g-btn-sm" style="color:var(--g-danger);border-color:var(--g-danger);" onclick="this.closest('.mm-level-card').remove()"><i data-lucide="trash-2" style="width:13px;height:13px;"></i></button>
|
||||
</div>
|
||||
<button class="g-btn g-btn-sm" style="width:100%;">编辑</button>
|
||||
</div>
|
||||
</div>
|
||||
<button class="mm-add-level-btn" onclick="openMmLevelDrawer()"><i data-lucide="plus" style="width:14px;height:14px;"></i>添加等级</button>
|
||||
|
||||
<!-- 会员日设置 -->
|
||||
<div class="mm-section-hd">会员日设置</div>
|
||||
@@ -344,31 +399,32 @@
|
||||
<div class="mm-ov-item"><div class="mm-ov-val">¥15,280</div><div class="mm-ov-label">累计消费</div></div>
|
||||
<div class="mm-ov-item"><div class="mm-ov-val">186</div><div class="mm-ov-label">消费次数</div></div>
|
||||
<div class="mm-ov-item"><div class="mm-ov-val">¥82.2</div><div class="mm-ov-label">平均客单价</div></div>
|
||||
<div class="mm-ov-item"><div class="mm-ov-val">¥2,350</div><div class="mm-ov-label">储值余额</div></div>
|
||||
<div class="mm-ov-item"><div class="mm-ov-val">¥2,350</div><div class="mm-ov-label">储值余额</div><div style="font-size:10px;color:var(--g-text-muted);margin-top:2px;">实充 ¥2,000 | 赠金 ¥350</div></div>
|
||||
<div class="mm-ov-item"><div class="mm-ov-val">8,620</div><div class="mm-ov-label">积分</div></div>
|
||||
</div>
|
||||
|
||||
<!-- 最近订单 -->
|
||||
<div class="mm-section-hd">最近订单</div>
|
||||
<table class="mm-mini-table">
|
||||
<thead><tr><th>日期</th><th>订单号</th><th>金额</th><th>状态</th></tr></thead>
|
||||
<thead><tr><th>日期</th><th>订单号</th><th>金额</th><th>状态</th><th style="width:50px;">操作</th></tr></thead>
|
||||
<tbody id="mmDrOrders">
|
||||
<tr><td>2026-02-11</td><td>OD20260211086</td><td>¥68.00</td><td><span class="g-tag g-tag-green">已完成</span></td></tr>
|
||||
<tr><td>2026-02-08</td><td>OD20260208052</td><td>¥95.50</td><td><span class="g-tag g-tag-green">已完成</span></td></tr>
|
||||
<tr><td>2026-02-05</td><td>OD20260205031</td><td>¥42.00</td><td><span class="g-tag g-tag-green">已完成</span></td></tr>
|
||||
<tr><td>2026-02-11</td><td>OD20260211086</td><td>¥68.00</td><td><span class="g-tag g-tag-green">已完成</span></td><td><a class="g-action" style="font-size:12px;">详情</a></td></tr>
|
||||
<tr><td>2026-02-08</td><td>OD20260208052</td><td>¥95.50</td><td><span class="g-tag g-tag-green">已完成</span></td><td><a class="g-action" style="font-size:12px;">详情</a></td></tr>
|
||||
<tr><td>2026-02-05</td><td>OD20260205031</td><td>¥42.00</td><td><span class="g-tag g-tag-green">已完成</span></td><td><a class="g-action" style="font-size:12px;">详情</a></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- 会员标签 -->
|
||||
<div style="margin-top:20px;">
|
||||
<div class="mm-section-hd">会员标签</div>
|
||||
<div class="mm-tag-list">
|
||||
<span class="g-pill checked" onclick="this.classList.toggle('checked')">高频</span>
|
||||
<span class="g-pill checked" onclick="this.classList.toggle('checked')">午餐常客</span>
|
||||
<span class="g-pill checked" onclick="this.classList.toggle('checked')">偏好辣味</span>
|
||||
<span class="g-pill" onclick="this.classList.toggle('checked')">下午茶</span>
|
||||
<span class="g-pill" onclick="this.classList.toggle('checked')">家庭聚餐</span>
|
||||
<span class="g-pill" onclick="this.classList.toggle('checked')">外卖为主</span>
|
||||
<div class="mm-tag-list" id="mmTagList">
|
||||
<span class="g-pill checked" onclick="this.classList.toggle('checked')">高频<span class="mm-tag-remove" onclick="event.stopPropagation();this.parentElement.remove()"><i data-lucide="x" style="width:10px;height:10px;"></i></span></span>
|
||||
<span class="g-pill checked" onclick="this.classList.toggle('checked')">午餐常客<span class="mm-tag-remove" onclick="event.stopPropagation();this.parentElement.remove()"><i data-lucide="x" style="width:10px;height:10px;"></i></span></span>
|
||||
<span class="g-pill checked" onclick="this.classList.toggle('checked')">偏好辣味<span class="mm-tag-remove" onclick="event.stopPropagation();this.parentElement.remove()"><i data-lucide="x" style="width:10px;height:10px;"></i></span></span>
|
||||
<span class="g-pill" onclick="this.classList.toggle('checked')">下午茶<span class="mm-tag-remove" onclick="event.stopPropagation();this.parentElement.remove()"><i data-lucide="x" style="width:10px;height:10px;"></i></span></span>
|
||||
<span class="g-pill" onclick="this.classList.toggle('checked')">家庭聚餐<span class="mm-tag-remove" onclick="event.stopPropagation();this.parentElement.remove()"><i data-lucide="x" style="width:10px;height:10px;"></i></span></span>
|
||||
<span class="g-pill" onclick="this.classList.toggle('checked')">外卖为主<span class="mm-tag-remove" onclick="event.stopPropagation();this.parentElement.remove()"><i data-lucide="x" style="width:10px;height:10px;"></i></span></span>
|
||||
<button class="mm-tag-add" id="mmTagAddBtn" onclick="showMmTagInput()"><i data-lucide="plus" style="width:12px;height:12px;"></i>自定义标签</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -377,6 +433,174 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 等级编辑抽屉 -->
|
||||
<div class="g-drawer-mask" id="mmLevelMask" onclick="closeMmLevelDrawer()"></div>
|
||||
<div class="g-drawer" id="mmLevelDrawer" style="width:520px;">
|
||||
<div class="g-drawer-hd">
|
||||
<div class="g-drawer-title" id="mmLevelTitle">编辑等级</div>
|
||||
<button class="g-drawer-close" onclick="closeMmLevelDrawer()"><i data-lucide="x" style="width:18px;height:18px;"></i></button>
|
||||
</div>
|
||||
<div class="g-drawer-bd">
|
||||
<div class="g-form-group">
|
||||
<label class="g-form-label required">等级名称</label>
|
||||
<input class="g-input" id="mmLevelName" placeholder="如:金卡会员">
|
||||
</div>
|
||||
<div class="g-form-group">
|
||||
<label class="g-form-label">等级图标</label>
|
||||
<div style="display:flex;gap:8px;">
|
||||
<span class="g-pill checked" onclick="selectMmIcon(this)"><i data-lucide="user" style="width:14px;height:14px;"></i>默认</span>
|
||||
<span class="g-pill" onclick="selectMmIcon(this)"><i data-lucide="award" style="width:14px;height:14px;"></i>奖章</span>
|
||||
<span class="g-pill" onclick="selectMmIcon(this)"><i data-lucide="trophy" style="width:14px;height:14px;"></i>奖杯</span>
|
||||
<span class="g-pill" onclick="selectMmIcon(this)"><i data-lucide="gem" style="width:14px;height:14px;"></i>钻石</span>
|
||||
<span class="g-pill" onclick="selectMmIcon(this)"><i data-lucide="crown" style="width:14px;height:14px;"></i>皇冠</span>
|
||||
<span class="g-pill" onclick="selectMmIcon(this)"><i data-lucide="star" style="width:14px;height:14px;"></i>星星</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="g-form-group">
|
||||
<label class="g-form-label">等级颜色</label>
|
||||
<div style="display:flex;gap:8px;">
|
||||
<span style="width:28px;height:28px;border-radius:50%;background:#999;cursor:pointer;border:2px solid transparent;" onclick="selectMmColor(this)"></span>
|
||||
<span style="width:28px;height:28px;border-radius:50%;background:#1890ff;cursor:pointer;border:2px solid var(--primary);" onclick="selectMmColor(this)"></span>
|
||||
<span style="width:28px;height:28px;border-radius:50%;background:#fa8c16;cursor:pointer;border:2px solid transparent;" onclick="selectMmColor(this)"></span>
|
||||
<span style="width:28px;height:28px;border-radius:50%;background:#722ed1;cursor:pointer;border:2px solid transparent;" onclick="selectMmColor(this)"></span>
|
||||
<span style="width:28px;height:28px;border-radius:50%;background:#eb2f96;cursor:pointer;border:2px solid transparent;" onclick="selectMmColor(this)"></span>
|
||||
<span style="width:28px;height:28px;border-radius:50%;background:#f5222d;cursor:pointer;border:2px solid transparent;" onclick="selectMmColor(this)"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="g-form-group">
|
||||
<label class="g-form-label required">升级规则</label>
|
||||
<div class="mm-upgrade-section">
|
||||
<div style="display:flex;gap:8px;margin-bottom:12px;">
|
||||
<span class="g-pill checked" onclick="selectMmUpgradeType(this,'amount')">按累计消费金额</span>
|
||||
<span class="g-pill" onclick="selectMmUpgradeType(this,'count')">按消费次数</span>
|
||||
<span class="g-pill" onclick="selectMmUpgradeType(this,'both')">同时满足</span>
|
||||
</div>
|
||||
<div id="mmUpgradeAmount">
|
||||
<div class="mm-upgrade-row">
|
||||
<span>累计消费满</span>
|
||||
<input class="g-input" type="number" style="width:120px;" placeholder="如:2000" value="2000">
|
||||
<span>元</span>
|
||||
</div>
|
||||
</div>
|
||||
<div id="mmUpgradeCount" style="display:none;">
|
||||
<div class="mm-upgrade-row">
|
||||
<span>消费满</span>
|
||||
<input class="g-input" type="number" style="width:120px;" placeholder="如:50" value="50">
|
||||
<span>次</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="g-hint">达到条件自动升级;连续90天未达标自动降一级</div>
|
||||
</div>
|
||||
|
||||
<div class="g-form-group">
|
||||
<label class="g-form-label">等级权益</label>
|
||||
|
||||
<!-- 折扣权益 -->
|
||||
<div class="mm-perk-card">
|
||||
<div class="mm-perk-card-hd">
|
||||
<span class="mm-perk-label">折扣权益</span>
|
||||
<div class="g-toggle on" onclick="toggleMmPerk(this)"></div>
|
||||
</div>
|
||||
<div class="mm-perk-card-bd">
|
||||
<span>全场</span>
|
||||
<input class="g-input" type="number" style="width:70px;text-align:center;" placeholder="9.5" value="9.5" step="0.1">
|
||||
<span>折</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 积分倍率 -->
|
||||
<div class="mm-perk-card">
|
||||
<div class="mm-perk-card-hd">
|
||||
<span class="mm-perk-label">积分倍率</span>
|
||||
<div class="g-toggle on" onclick="toggleMmPerk(this)"></div>
|
||||
</div>
|
||||
<div class="mm-perk-card-bd">
|
||||
<span>消费积分</span>
|
||||
<input class="g-input" type="number" style="width:70px;text-align:center;" placeholder="1.5" value="1.5" step="0.1">
|
||||
<span>倍</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 生日特权 -->
|
||||
<div class="mm-perk-card">
|
||||
<div class="mm-perk-card-hd">
|
||||
<span class="mm-perk-label">生日特权</span>
|
||||
<div class="g-toggle on" onclick="toggleMmPerk(this)"></div>
|
||||
</div>
|
||||
<div class="mm-perk-card-bd">
|
||||
<div style="display:flex;flex-direction:column;gap:8px;width:100%;">
|
||||
<label style="display:flex;align-items:center;gap:6px;font-size:12px;cursor:pointer;">
|
||||
<input type="checkbox" checked> 生日双倍积分
|
||||
</label>
|
||||
<label style="display:flex;align-items:center;gap:6px;font-size:12px;cursor:pointer;">
|
||||
<input type="checkbox" checked> 生日赠券
|
||||
</label>
|
||||
<div style="display:flex;align-items:center;gap:6px;margin-left:20px;">
|
||||
<div class="mm-coupon-mini">满30减5 <span class="mm-coupon-mini-remove" onclick="this.parentElement.remove()"><i data-lucide="x" style="width:10px;height:10px;"></i></span></div>
|
||||
<button class="mm-add-coupon-link" onclick="openProductPicker({title:'选择优惠券',onConfirm:function(){}})"><i data-lucide="plus" style="width:11px;height:11px;"></i>选券</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 每月赠券 -->
|
||||
<div class="mm-perk-card">
|
||||
<div class="mm-perk-card-hd">
|
||||
<span class="mm-perk-label">每月赠券</span>
|
||||
<div class="g-toggle" onclick="toggleMmPerk(this)"></div>
|
||||
</div>
|
||||
<div class="mm-perk-card-bd hidden">
|
||||
<div style="display:flex;flex-direction:column;gap:8px;width:100%;">
|
||||
<div style="display:flex;align-items:center;gap:6px;font-size:12px;">
|
||||
<span>每月</span>
|
||||
<input class="g-input" type="number" style="width:50px;text-align:center;" placeholder="1" value="1">
|
||||
<span>日自动发放以下优惠券:</span>
|
||||
</div>
|
||||
<div style="display:flex;align-items:center;gap:6px;">
|
||||
<div class="mm-coupon-mini">满50减8 <span class="mm-coupon-mini-remove" onclick="this.parentElement.remove()"><i data-lucide="x" style="width:10px;height:10px;"></i></span></div>
|
||||
<button class="mm-add-coupon-link" onclick="openProductPicker({title:'选择优惠券',onConfirm:function(){}})"><i data-lucide="plus" style="width:11px;height:11px;"></i>选券</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 免配送费 -->
|
||||
<div class="mm-perk-card">
|
||||
<div class="mm-perk-card-hd">
|
||||
<span class="mm-perk-label">免配送费</span>
|
||||
<div class="g-toggle" onclick="toggleMmPerk(this)"></div>
|
||||
</div>
|
||||
<div class="mm-perk-card-bd hidden">
|
||||
<span>每月免配送费</span>
|
||||
<input class="g-input" type="number" style="width:60px;text-align:center;" placeholder="5" value="5">
|
||||
<span>次</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 优先配送 -->
|
||||
<div class="mm-perk-card">
|
||||
<div class="mm-perk-card-hd">
|
||||
<span class="mm-perk-label">优先配送</span>
|
||||
<div class="g-toggle" onclick="toggleMmPerk(this)"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 专属客服 -->
|
||||
<div class="mm-perk-card">
|
||||
<div class="mm-perk-card-hd">
|
||||
<span class="mm-perk-label">专属客服</span>
|
||||
<div class="g-toggle" onclick="toggleMmPerk(this)"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="g-drawer-ft">
|
||||
<button class="g-btn" onclick="closeMmLevelDrawer()">取消</button>
|
||||
<button class="g-btn g-btn-primary" onclick="closeMmLevelDrawer()">保存</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
/* Tab 切换 */
|
||||
function switchMmTab(el, tab) {
|
||||
@@ -398,5 +622,77 @@
|
||||
document.getElementById('mmDrawer').classList.remove('open');
|
||||
}
|
||||
|
||||
/* 等级编辑抽屉 */
|
||||
function openMmLevelDrawer(name) {
|
||||
document.getElementById('mmLevelMask').classList.add('open');
|
||||
document.getElementById('mmLevelDrawer').classList.add('open');
|
||||
document.getElementById('mmLevelTitle').textContent = '编辑等级 - ' + name;
|
||||
document.getElementById('mmLevelName').value = name;
|
||||
if (typeof lucide !== 'undefined') lucide.createIcons();
|
||||
}
|
||||
function closeMmLevelDrawer() {
|
||||
document.getElementById('mmLevelMask').classList.remove('open');
|
||||
document.getElementById('mmLevelDrawer').classList.remove('open');
|
||||
}
|
||||
function selectMmUpgradeType(el, type) {
|
||||
el.parentElement.querySelectorAll('.g-pill').forEach(function(p){ p.classList.remove('checked'); });
|
||||
el.classList.add('checked');
|
||||
document.getElementById('mmUpgradeAmount').style.display = (type === 'amount' || type === 'both') ? '' : 'none';
|
||||
document.getElementById('mmUpgradeCount').style.display = (type === 'count' || type === 'both') ? '' : 'none';
|
||||
}
|
||||
function toggleMmPerk(toggleEl) {
|
||||
toggleEl.classList.toggle('on');
|
||||
var card = toggleEl.closest('.mm-perk-card');
|
||||
var bd = card.querySelector('.mm-perk-card-bd');
|
||||
if (bd) {
|
||||
bd.classList.toggle('hidden', !toggleEl.classList.contains('on'));
|
||||
}
|
||||
}
|
||||
function selectMmIcon(el) {
|
||||
el.parentElement.querySelectorAll('.g-pill').forEach(function(p){ p.classList.remove('checked'); });
|
||||
el.classList.add('checked');
|
||||
}
|
||||
function selectMmColor(el) {
|
||||
el.parentElement.querySelectorAll('span').forEach(function(s){ s.style.borderColor = 'transparent'; });
|
||||
el.style.borderColor = el.style.background;
|
||||
}
|
||||
function addMmPerk() {
|
||||
var row = document.createElement('div');
|
||||
row.className = 'mm-perk-row';
|
||||
row.innerHTML = '<input class="g-input" placeholder="请输入权益描述"><button class="mm-perk-remove" onclick="this.parentElement.remove()"><i data-lucide="trash-2" style="width:14px;height:14px;"></i></button>';
|
||||
document.getElementById('mmPerkList').appendChild(row);
|
||||
if (typeof lucide !== 'undefined') lucide.createIcons();
|
||||
}
|
||||
|
||||
/* 自定义标签 */
|
||||
function showMmTagInput() {
|
||||
var btn = document.getElementById('mmTagAddBtn');
|
||||
var input = document.createElement('input');
|
||||
input.className = 'mm-tag-input';
|
||||
input.placeholder = '输入标签名';
|
||||
input.onkeydown = function(e) {
|
||||
if (e.key === 'Enter' && this.value.trim()) {
|
||||
var tag = document.createElement('span');
|
||||
tag.className = 'g-pill checked';
|
||||
tag.onclick = function(){ this.classList.toggle('checked'); };
|
||||
tag.textContent = this.value.trim();
|
||||
var rm = document.createElement('span');
|
||||
rm.className = 'mm-tag-remove';
|
||||
rm.innerHTML = '<i data-lucide="x" style="width:10px;height:10px;"></i>';
|
||||
rm.onclick = function(e){ e.stopPropagation(); this.parentElement.remove(); };
|
||||
tag.appendChild(rm);
|
||||
btn.parentElement.insertBefore(tag, btn);
|
||||
this.remove();
|
||||
btn.style.display = '';
|
||||
if (typeof lucide !== 'undefined') lucide.createIcons();
|
||||
}
|
||||
if (e.key === 'Escape') { this.remove(); btn.style.display = ''; }
|
||||
};
|
||||
input.onblur = function() { this.remove(); btn.style.display = ''; };
|
||||
btn.style.display = 'none';
|
||||
btn.parentElement.insertBefore(input, btn);
|
||||
input.focus();
|
||||
}
|
||||
|
||||
if (typeof lucide !== 'undefined') lucide.createIcons();
|
||||
</script>
|
||||
|
||||
@@ -76,7 +76,11 @@
|
||||
align-items:center; justify-content:center; color:#ccc;
|
||||
}
|
||||
.pt-prod-bd { padding:14px 16px; }
|
||||
.pt-prod-name { font-size:14px; font-weight:600; color:var(--g-text); margin-bottom:8px; }
|
||||
.pt-prod-name { font-size:14px; font-weight:600; color:var(--g-text); margin-bottom:8px; display:flex; align-items:center; gap:6px; }
|
||||
.pt-type-tag { font-size:11px; font-weight:500; padding:1px 6px; border-radius:4px; flex-shrink:0; }
|
||||
.pt-type-tag.blue { background:color-mix(in srgb, var(--primary) 12%, #fff); color:var(--primary); }
|
||||
.pt-type-tag.green { background:color-mix(in srgb, var(--g-success) 12%, #fff); color:var(--g-success); }
|
||||
.pt-type-tag.orange { background:color-mix(in srgb, var(--g-warning) 12%, #fff); color:var(--g-warning); }
|
||||
.pt-prod-price { font-size:18px; font-weight:700; color:var(--primary); margin-bottom:6px; }
|
||||
.pt-prod-price .pt-cash { font-size:13px; font-weight:500; color:var(--g-text-secondary); margin-left:4px; }
|
||||
.pt-prod-meta { display:flex; gap:16px; font-size:12px; color:var(--g-text-muted); margin-bottom:10px; }
|
||||
@@ -98,6 +102,29 @@
|
||||
/* 兑换方式 pill 组 */
|
||||
.pt-exchange-pills { display:flex; gap:10px; }
|
||||
|
||||
/* 通知 pill 多选 */
|
||||
.pt-notify-pills { display:flex; gap:10px; }
|
||||
.pt-notify-pills .g-pill { position:relative; padding-left:24px; }
|
||||
.pt-notify-pills .g-pill::before {
|
||||
content:''; position:absolute; left:8px; top:50%; transform:translateY(-50%);
|
||||
width:12px; height:12px; border:1.5px solid #ccc; border-radius:3px; transition:all var(--g-transition);
|
||||
}
|
||||
.pt-notify-pills .g-pill.checked::before {
|
||||
background:var(--primary); border-color:var(--primary);
|
||||
background-image:url("data:image/svg+xml,%3Csvg viewBox='0 0 12 12' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M2.5 6L5 8.5L9.5 4' stroke='white' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
|
||||
}
|
||||
|
||||
/* 兑换记录表格 */
|
||||
.pt-rec-status { display:inline-flex; align-items:center; gap:4px; font-size:12px; }
|
||||
.pt-rec-status::before { content:''; width:6px; height:6px; border-radius:50%; }
|
||||
.pt-rec-status.green::before { background:var(--g-success); }
|
||||
.pt-rec-status.orange::before { background:var(--g-warning); }
|
||||
.pt-rec-status.gray::before { background:#bbb; }
|
||||
.pt-rec-status.red::before { background:var(--g-danger); }
|
||||
.pt-rec-member { display:flex; flex-direction:column; gap:2px; }
|
||||
.pt-rec-member-name { font-size:13px; font-weight:500; color:var(--g-text); }
|
||||
.pt-rec-member-phone { font-size:12px; color:var(--g-text-muted); }
|
||||
|
||||
/* 保存栏 */
|
||||
.pt-save-bar { margin-top:20px; display:flex; justify-content:flex-end; }
|
||||
</style>
|
||||
@@ -107,6 +134,7 @@
|
||||
<div class="pt-seg">
|
||||
<button class="pt-seg-item active" onclick="switchPtTab(this, 'rules')">积分规则</button>
|
||||
<button class="pt-seg-item" onclick="switchPtTab(this, 'products')">兑换商品</button>
|
||||
<button class="pt-seg-item" onclick="switchPtTab(this, 'records')">兑换记录</button>
|
||||
</div>
|
||||
|
||||
<!-- ==================== TAB 1: 积分规则 ==================== -->
|
||||
@@ -214,7 +242,7 @@
|
||||
<div class="pt-prod-card">
|
||||
<div class="pt-prod-img"><i data-lucide="image" style="width:32px;height:32px;"></i></div>
|
||||
<div class="pt-prod-bd">
|
||||
<div class="pt-prod-name">可乐兑换券</div>
|
||||
<div class="pt-prod-name">可乐兑换券<span class="pt-type-tag blue">商品</span></div>
|
||||
<div class="pt-prod-price">100积分</div>
|
||||
<div class="pt-prod-meta">
|
||||
<span>库存 50</span>
|
||||
@@ -233,7 +261,7 @@
|
||||
<div class="pt-prod-card">
|
||||
<div class="pt-prod-img"><i data-lucide="image" style="width:32px;height:32px;"></i></div>
|
||||
<div class="pt-prod-bd">
|
||||
<div class="pt-prod-name">凉拌黄瓜</div>
|
||||
<div class="pt-prod-name">凉拌黄瓜<span class="pt-type-tag blue">商品</span></div>
|
||||
<div class="pt-prod-price">200积分</div>
|
||||
<div class="pt-prod-meta">
|
||||
<span>库存 30</span>
|
||||
@@ -252,7 +280,7 @@
|
||||
<div class="pt-prod-card">
|
||||
<div class="pt-prod-img"><i data-lucide="image" style="width:32px;height:32px;"></i></div>
|
||||
<div class="pt-prod-bd">
|
||||
<div class="pt-prod-name">满20减5券</div>
|
||||
<div class="pt-prod-name">满20减5券<span class="pt-type-tag green">优惠券</span></div>
|
||||
<div class="pt-prod-price">300积分</div>
|
||||
<div class="pt-prod-meta">
|
||||
<span>库存 100</span>
|
||||
@@ -271,7 +299,7 @@
|
||||
<div class="pt-prod-card">
|
||||
<div class="pt-prod-img"><i data-lucide="image" style="width:32px;height:32px;"></i></div>
|
||||
<div class="pt-prod-bd">
|
||||
<div class="pt-prod-name">招牌奶茶</div>
|
||||
<div class="pt-prod-name">招牌奶茶<span class="pt-type-tag blue">商品</span></div>
|
||||
<div class="pt-prod-price">500积分<span class="pt-cash">+ ¥3.00</span></div>
|
||||
<div class="pt-prod-meta">
|
||||
<span>库存 20</span>
|
||||
@@ -290,7 +318,7 @@
|
||||
<div class="pt-prod-card">
|
||||
<div class="pt-prod-img"><i data-lucide="image" style="width:32px;height:32px;"></i></div>
|
||||
<div class="pt-prod-bd">
|
||||
<div class="pt-prod-name">双人套餐券</div>
|
||||
<div class="pt-prod-name">双人套餐券<span class="pt-type-tag green">优惠券</span></div>
|
||||
<div class="pt-prod-price">1000积分</div>
|
||||
<div class="pt-prod-meta">
|
||||
<span>库存 10</span>
|
||||
@@ -309,7 +337,7 @@
|
||||
<div class="pt-prod-card pt-off">
|
||||
<div class="pt-prod-img"><i data-lucide="image" style="width:32px;height:32px;"></i></div>
|
||||
<div class="pt-prod-bd">
|
||||
<div class="pt-prod-name">定制保温杯</div>
|
||||
<div class="pt-prod-name">定制保温杯<span class="pt-type-tag orange">实物</span></div>
|
||||
<div class="pt-prod-price">2000积分</div>
|
||||
<div class="pt-prod-meta">
|
||||
<span>库存 0</span>
|
||||
@@ -326,6 +354,145 @@
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ==================== TAB 3: 兑换记录 ==================== -->
|
||||
<div id="ptTabRecords" style="display:none;">
|
||||
|
||||
<!-- 筛选工具栏 -->
|
||||
<div class="pt-toolbar">
|
||||
<select style="width:120px;">
|
||||
<option value="">全部类型</option>
|
||||
<option>兑换商品</option>
|
||||
<option>兑换优惠券</option>
|
||||
<option>兑换实物</option>
|
||||
</select>
|
||||
<select style="width:120px;">
|
||||
<option value="">全部状态</option>
|
||||
<option>待领取</option>
|
||||
<option>已发放</option>
|
||||
<option>已完成</option>
|
||||
<option>已取消</option>
|
||||
</select>
|
||||
<input type="text" placeholder="搜索会员/商品名称" style="width:200px;">
|
||||
<div style="flex:1;"></div>
|
||||
<button class="g-btn g-btn-sm"><i data-lucide="download" style="width:13px;height:13px;"></i>导出</button>
|
||||
</div>
|
||||
|
||||
<!-- 统计 -->
|
||||
<div class="pt-stats" style="grid-template-columns:repeat(3,1fr);">
|
||||
<div class="pt-stat-card">
|
||||
<div class="pt-stat-label">今日兑换</div>
|
||||
<div class="pt-stat-value primary">12</div>
|
||||
</div>
|
||||
<div class="pt-stat-card">
|
||||
<div class="pt-stat-label">待领取实物</div>
|
||||
<div class="pt-stat-value orange">3</div>
|
||||
</div>
|
||||
<div class="pt-stat-card">
|
||||
<div class="pt-stat-label">本月消耗积分</div>
|
||||
<div class="pt-stat-value">8,400</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 兑换记录表格 -->
|
||||
<div class="g-card" style="padding:0;">
|
||||
<table class="g-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>兑换单号</th>
|
||||
<th>会员</th>
|
||||
<th>兑换商品</th>
|
||||
<th>类型</th>
|
||||
<th>消耗积分</th>
|
||||
<th>兑换时间</th>
|
||||
<th>状态</th>
|
||||
<th style="width:100px;">操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="font-family:monospace;font-size:12px;">PT20260212001</td>
|
||||
<td><div class="pt-rec-member"><span class="pt-rec-member-name">张三</span><span class="pt-rec-member-phone">138****6789</span></div></td>
|
||||
<td>定制保温杯</td>
|
||||
<td><span class="pt-type-tag orange">实物</span></td>
|
||||
<td style="font-weight:600;">2,000</td>
|
||||
<td style="font-size:12px;color:var(--g-text-secondary);">2026-02-12 10:30</td>
|
||||
<td><span class="pt-rec-status orange">待领取</span></td>
|
||||
<td><a class="g-action" onclick="openPtVerifyDrawer()">核销</a><a class="g-action">详情</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="font-family:monospace;font-size:12px;">PT20260212002</td>
|
||||
<td><div class="pt-rec-member"><span class="pt-rec-member-name">李四</span><span class="pt-rec-member-phone">139****1234</span></div></td>
|
||||
<td>可乐兑换券</td>
|
||||
<td><span class="pt-type-tag blue">商品</span></td>
|
||||
<td style="font-weight:600;">100</td>
|
||||
<td style="font-size:12px;color:var(--g-text-secondary);">2026-02-12 09:45</td>
|
||||
<td><span class="pt-rec-status green">已发放</span></td>
|
||||
<td><a class="g-action">详情</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="font-family:monospace;font-size:12px;">PT20260211003</td>
|
||||
<td><div class="pt-rec-member"><span class="pt-rec-member-name">王五</span><span class="pt-rec-member-phone">137****5678</span></div></td>
|
||||
<td>满20减5券</td>
|
||||
<td><span class="pt-type-tag green">优惠券</span></td>
|
||||
<td style="font-weight:600;">300</td>
|
||||
<td style="font-size:12px;color:var(--g-text-secondary);">2026-02-11 18:20</td>
|
||||
<td><span class="pt-rec-status green">已发放</span></td>
|
||||
<td><a class="g-action">详情</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="font-family:monospace;font-size:12px;">PT20260211004</td>
|
||||
<td><div class="pt-rec-member"><span class="pt-rec-member-name">赵六</span><span class="pt-rec-member-phone">136****4321</span></div></td>
|
||||
<td>定制保温杯</td>
|
||||
<td><span class="pt-type-tag orange">实物</span></td>
|
||||
<td style="font-weight:600;">2,000</td>
|
||||
<td style="font-size:12px;color:var(--g-text-secondary);">2026-02-11 14:10</td>
|
||||
<td><span class="pt-rec-status orange">待领取</span></td>
|
||||
<td><a class="g-action" onclick="openPtVerifyDrawer()">核销</a><a class="g-action">详情</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="font-family:monospace;font-size:12px;">PT20260210005</td>
|
||||
<td><div class="pt-rec-member"><span class="pt-rec-member-name">孙七</span><span class="pt-rec-member-phone">135****8765</span></div></td>
|
||||
<td>招牌奶茶</td>
|
||||
<td><span class="pt-type-tag blue">商品</span></td>
|
||||
<td style="font-weight:600;">500</td>
|
||||
<td style="font-size:12px;color:var(--g-text-secondary);">2026-02-10 16:55</td>
|
||||
<td><span class="pt-rec-status green">已完成</span></td>
|
||||
<td><a class="g-action">详情</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="font-family:monospace;font-size:12px;">PT20260210006</td>
|
||||
<td><div class="pt-rec-member"><span class="pt-rec-member-name">周八</span><span class="pt-rec-member-phone">133****2222</span></div></td>
|
||||
<td>双人套餐券</td>
|
||||
<td><span class="pt-type-tag green">优惠券</span></td>
|
||||
<td style="font-weight:600;">1,000</td>
|
||||
<td style="font-size:12px;color:var(--g-text-secondary);">2026-02-10 11:30</td>
|
||||
<td><span class="pt-rec-status gray">已取消</span></td>
|
||||
<td><a class="g-action">详情</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="font-family:monospace;font-size:12px;">PT20260209007</td>
|
||||
<td><div class="pt-rec-member"><span class="pt-rec-member-name">吴九</span><span class="pt-rec-member-phone">131****9999</span></div></td>
|
||||
<td>定制保温杯</td>
|
||||
<td><span class="pt-type-tag orange">实物</span></td>
|
||||
<td style="font-weight:600;">2,000</td>
|
||||
<td style="font-size:12px;color:var(--g-text-secondary);">2026-02-09 09:00</td>
|
||||
<td><span class="pt-rec-status green">已完成</span></td>
|
||||
<td><a class="g-action">详情</a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- 分页 -->
|
||||
<div class="g-pagination" style="margin-top:16px;">
|
||||
<button class="g-page-btn" disabled><i data-lucide="chevron-left" style="width:14px;height:14px;"></i></button>
|
||||
<button class="g-page-btn active">1</button>
|
||||
<button class="g-page-btn">2</button>
|
||||
<button class="g-page-btn">3</button>
|
||||
<button class="g-page-btn"><i data-lucide="chevron-right" style="width:14px;height:14px;"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ==================== 添加/编辑兑换商品抽屉 ==================== -->
|
||||
@@ -337,15 +504,77 @@
|
||||
</div>
|
||||
<div class="g-drawer-bd">
|
||||
|
||||
<!-- 商品名称 -->
|
||||
<!-- 兑换类型 -->
|
||||
<div class="g-form-group">
|
||||
<label class="g-form-label required">商品名称</label>
|
||||
<input class="g-input" placeholder="请输入兑换商品名称">
|
||||
<label class="g-form-label required">兑换类型</label>
|
||||
<div class="pt-exchange-pills">
|
||||
<span class="g-pill checked" onclick="selectPtRedeemType(this, 'product')">兑换商品</span>
|
||||
<span class="g-pill" onclick="selectPtRedeemType(this, 'coupon')">兑换优惠券</span>
|
||||
<span class="g-pill" onclick="selectPtRedeemType(this, 'physical')">兑换实物</span>
|
||||
</div>
|
||||
<div class="g-hint" id="ptRedeemHintProduct">顾客兑换后系统自动发放商品兑换券,下单时该商品免费</div>
|
||||
<div class="g-hint" id="ptRedeemHintCoupon" style="display:none;">顾客兑换后优惠券直接发到券包</div>
|
||||
<div class="g-hint" id="ptRedeemHintPhysical" style="display:none;">实物商品需到店自提,不走线上履约</div>
|
||||
</div>
|
||||
|
||||
<!-- 兑换商品:选择商品 -->
|
||||
<div id="ptFieldProduct">
|
||||
<div class="g-form-group">
|
||||
<label class="g-form-label required">关联商品</label>
|
||||
<div id="ptSelectedProduct" style="display:none;padding:10px 12px;background:#f8f9fb;border-radius:8px;border:1px solid #e5e7eb;margin-bottom:8px;display:flex;align-items:center;gap:10px;">
|
||||
<div style="width:40px;height:40px;background:#eee;border-radius:6px;display:flex;align-items:center;justify-content:center;color:#bbb;flex-shrink:0;"><i data-lucide="image" style="width:18px;height:18px;"></i></div>
|
||||
<div style="flex:1;">
|
||||
<div style="font-size:13px;font-weight:500;">招牌奶茶</div>
|
||||
<div style="font-size:12px;color:var(--g-text-muted);">原价 ¥15.00</div>
|
||||
</div>
|
||||
<button style="background:none;border:none;color:var(--g-text-muted);cursor:pointer;" onclick="this.parentElement.style.display='none'"><i data-lucide="x" style="width:14px;height:14px;"></i></button>
|
||||
</div>
|
||||
<button class="g-btn g-btn-sm" onclick="openProductPicker({title:'选择兑换商品',subtitle:'积分商城',onConfirm:function(){}})"><i data-lucide="plus" style="width:13px;height:13px;"></i>选择商品/套餐</button>
|
||||
<div class="g-hint">兑换后系统自动生成该商品的兑换券</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 兑换优惠券:选择券 -->
|
||||
<div id="ptFieldCoupon" style="display:none;">
|
||||
<div class="g-form-group">
|
||||
<label class="g-form-label required">关联优惠券</label>
|
||||
<select class="g-select" style="width:100%;">
|
||||
<option value="">请选择优惠券</option>
|
||||
<option>新用户满减券(满50减15)</option>
|
||||
<option>全场8折券</option>
|
||||
<option>免配送费券</option>
|
||||
<option>满30减5券</option>
|
||||
<option>满80减20券</option>
|
||||
</select>
|
||||
<div class="g-hint">选择已在优惠券管理中创建的券,兑换后直接发到顾客券包</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 兑换实物:名称+描述 -->
|
||||
<div id="ptFieldPhysical" style="display:none;">
|
||||
<div class="g-form-group">
|
||||
<label class="g-form-label required">实物名称</label>
|
||||
<input class="g-input" placeholder="如:定制保温杯、品牌帆布袋">
|
||||
</div>
|
||||
<div class="g-form-group">
|
||||
<label class="g-form-label">领取方式</label>
|
||||
<div style="display:flex;gap:8px;">
|
||||
<span class="g-pill checked" onclick="this.parentElement.querySelectorAll('.g-pill').forEach(function(p){p.classList.remove('checked')});this.classList.add('checked')">到店自提</span>
|
||||
<span class="g-pill" onclick="this.parentElement.querySelectorAll('.g-pill').forEach(function(p){p.classList.remove('checked')});this.classList.add('checked')">快递配送</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 商品名称(展示名) -->
|
||||
<div class="g-form-group">
|
||||
<label class="g-form-label required">展示名称</label>
|
||||
<input class="g-input" placeholder="如:招牌奶茶兑换券、满50减15券">
|
||||
<div class="g-hint">顾客在积分商城看到的名称</div>
|
||||
</div>
|
||||
|
||||
<!-- 商品图片 -->
|
||||
<div class="g-form-group">
|
||||
<label class="g-form-label">商品图片</label>
|
||||
<label class="g-form-label">展示图片</label>
|
||||
<div class="pt-upload-placeholder">
|
||||
<i data-lucide="upload-cloud" style="width:28px;height:28px;"></i>
|
||||
<span>点击上传商品图片</span>
|
||||
@@ -354,8 +583,8 @@
|
||||
|
||||
<!-- 兑换方式 -->
|
||||
<div class="g-form-group">
|
||||
<label class="g-form-label required">兑换方式</label>
|
||||
<div class="pt-exchange-pills">
|
||||
<label class="g-form-label required">兑换积分</label>
|
||||
<div class="pt-exchange-pills" style="margin-bottom:8px;">
|
||||
<span class="g-pill checked" onclick="selectPtExchangeType(this, 'points')">纯积分</span>
|
||||
<span class="g-pill" onclick="selectPtExchangeType(this, 'mixed')">积分+现金</span>
|
||||
</div>
|
||||
@@ -397,6 +626,16 @@
|
||||
<textarea class="g-textarea" rows="4" placeholder="请输入商品描述信息,如使用规则、有效期等"></textarea>
|
||||
</div>
|
||||
|
||||
<!-- 到账通知 -->
|
||||
<div class="g-form-group">
|
||||
<label class="g-form-label">到账通知</label>
|
||||
<div class="pt-notify-pills" id="ptNotifyPills">
|
||||
<span class="g-pill checked" onclick="togglePill(this)">站内消息</span>
|
||||
<span class="g-pill" onclick="togglePill(this)">短信通知</span>
|
||||
</div>
|
||||
<div class="g-hint">选择兑换成功后通知顾客的方式,实物商品建议开启短信通知</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="g-drawer-ft">
|
||||
<button class="g-btn" onclick="closePtDrawer()">取消</button>
|
||||
@@ -404,6 +643,54 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ==================== 核销抽屉 ==================== -->
|
||||
<div class="g-drawer-mask" id="ptVerifyMask" onclick="closePtVerifyDrawer()"></div>
|
||||
<div class="g-drawer" id="ptVerifyDrawer" style="width:440px;">
|
||||
<div class="g-drawer-hd">
|
||||
<span class="g-drawer-title">兑换核销</span>
|
||||
<button class="g-drawer-close" onclick="closePtVerifyDrawer()">×</button>
|
||||
</div>
|
||||
<div class="g-drawer-bd">
|
||||
|
||||
<!-- 兑换信息 -->
|
||||
<div style="background:#f8f9fb;border-radius:10px;padding:16px;margin-bottom:20px;">
|
||||
<div style="display:flex;align-items:center;gap:12px;margin-bottom:12px;">
|
||||
<div style="width:48px;height:48px;background:#eee;border-radius:8px;display:flex;align-items:center;justify-content:center;color:#bbb;flex-shrink:0;"><i data-lucide="image" style="width:22px;height:22px;"></i></div>
|
||||
<div>
|
||||
<div style="font-size:14px;font-weight:600;color:var(--g-text);margin-bottom:2px;">定制保温杯</div>
|
||||
<span class="pt-type-tag orange">实物</span>
|
||||
</div>
|
||||
</div>
|
||||
<div style="display:grid;grid-template-columns:1fr 1fr;gap:8px;font-size:13px;">
|
||||
<div><span style="color:var(--g-text-muted);">兑换单号</span><div style="font-family:monospace;margin-top:2px;">PT20260212001</div></div>
|
||||
<div><span style="color:var(--g-text-muted);">消耗积分</span><div style="font-weight:600;color:var(--primary);margin-top:2px;">2,000</div></div>
|
||||
<div><span style="color:var(--g-text-muted);">兑换会员</span><div style="margin-top:2px;">张三 (138****6789)</div></div>
|
||||
<div><span style="color:var(--g-text-muted);">兑换时间</span><div style="margin-top:2px;">2026-02-12 10:30</div></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 核销方式 -->
|
||||
<div class="g-form-group">
|
||||
<label class="g-form-label">核销方式</label>
|
||||
<div style="display:flex;gap:10px;">
|
||||
<span class="g-pill checked" onclick="this.parentElement.querySelectorAll('.g-pill').forEach(function(p){p.classList.remove('checked')});this.classList.add('checked')">扫码核销</span>
|
||||
<span class="g-pill" onclick="this.parentElement.querySelectorAll('.g-pill').forEach(function(p){p.classList.remove('checked')});this.classList.add('checked')">手动核销</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 备注 -->
|
||||
<div class="g-form-group">
|
||||
<label class="g-form-label">核销备注</label>
|
||||
<textarea class="g-textarea" rows="2" placeholder="可选,如:顾客已到店领取"></textarea>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="g-drawer-ft">
|
||||
<button class="g-btn" onclick="closePtVerifyDrawer()">取消</button>
|
||||
<button class="g-btn g-btn-primary">确认核销</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
/* Tab 切换 */
|
||||
function switchPtTab(el, tab) {
|
||||
@@ -411,6 +698,7 @@
|
||||
el.classList.add('active');
|
||||
document.getElementById('ptTabRules').style.display = tab === 'rules' ? '' : 'none';
|
||||
document.getElementById('ptTabProducts').style.display = tab === 'products' ? '' : 'none';
|
||||
document.getElementById('ptTabRecords').style.display = tab === 'records' ? '' : 'none';
|
||||
}
|
||||
|
||||
/* Toggle 开关 */
|
||||
@@ -426,9 +714,29 @@
|
||||
hint.style.display = el.textContent.trim() === '按年清零' ? '' : 'none';
|
||||
}
|
||||
|
||||
/* 兑换方式 pill 单选 */
|
||||
/* 兑换类型切换(商品/优惠券/实物) */
|
||||
function selectPtRedeemType(el, type) {
|
||||
el.parentElement.querySelectorAll('.g-pill').forEach(function(p) { p.classList.remove('checked'); });
|
||||
el.classList.add('checked');
|
||||
document.getElementById('ptFieldProduct').style.display = type === 'product' ? '' : 'none';
|
||||
document.getElementById('ptFieldCoupon').style.display = type === 'coupon' ? '' : 'none';
|
||||
document.getElementById('ptFieldPhysical').style.display = type === 'physical' ? '' : 'none';
|
||||
document.getElementById('ptRedeemHintProduct').style.display = type === 'product' ? '' : 'none';
|
||||
document.getElementById('ptRedeemHintCoupon').style.display = type === 'coupon' ? '' : 'none';
|
||||
document.getElementById('ptRedeemHintPhysical').style.display = type === 'physical' ? '' : 'none';
|
||||
/* 自动设置通知默认值:实物默认勾选短信 */
|
||||
var pills = document.querySelectorAll('#ptNotifyPills .g-pill');
|
||||
if (type === 'physical') {
|
||||
pills.forEach(function(p) { p.classList.add('checked'); });
|
||||
} else {
|
||||
pills[0].classList.add('checked');
|
||||
pills[1].classList.remove('checked');
|
||||
}
|
||||
}
|
||||
|
||||
/* 兑换方式 pill 单选(纯积分/积分+现金) */
|
||||
function selectPtExchangeType(el, type) {
|
||||
document.querySelectorAll('.pt-exchange-pills .g-pill').forEach(function(p) { p.classList.remove('checked'); });
|
||||
el.parentElement.querySelectorAll('.g-pill').forEach(function(p) { p.classList.remove('checked'); });
|
||||
el.classList.add('checked');
|
||||
document.getElementById('ptCashField').style.display = type === 'mixed' ? '' : 'none';
|
||||
}
|
||||
@@ -443,6 +751,21 @@
|
||||
document.getElementById('ptDrawer').classList.remove('open');
|
||||
}
|
||||
|
||||
/* 通知 pill 多选 */
|
||||
function togglePill(el) {
|
||||
el.classList.toggle('checked');
|
||||
}
|
||||
|
||||
/* 核销抽屉 */
|
||||
function openPtVerifyDrawer() {
|
||||
document.getElementById('ptVerifyMask').classList.add('open');
|
||||
document.getElementById('ptVerifyDrawer').classList.add('open');
|
||||
}
|
||||
function closePtVerifyDrawer() {
|
||||
document.getElementById('ptVerifyMask').classList.remove('open');
|
||||
document.getElementById('ptVerifyDrawer').classList.remove('open');
|
||||
}
|
||||
|
||||
/* 初始化 Lucide 图标 */
|
||||
if (typeof lucide !== 'undefined') { lucide.createIcons(); }
|
||||
</script>
|
||||
|
||||
284
pages/mkt-calendar.html
Normal file
284
pages/mkt-calendar.html
Normal file
@@ -0,0 +1,284 @@
|
||||
<!-- 营销日历页 -->
|
||||
<style>
|
||||
.page-mc { max-width:1100px; }
|
||||
|
||||
/* 顶部控制栏 */
|
||||
.mc-header {
|
||||
display:flex; align-items:center; justify-content:space-between; margin-bottom:16px;
|
||||
background:#fff; border-radius:10px; padding:14px 20px; box-shadow:var(--g-shadow-sm);
|
||||
}
|
||||
.mc-month-nav { display:flex; align-items:center; gap:12px; }
|
||||
.mc-month-nav button {
|
||||
width:32px; height:32px; border:1px solid #e5e7eb; border-radius:8px; background:#fff;
|
||||
cursor:pointer; display:flex; align-items:center; justify-content:center;
|
||||
transition:all var(--g-transition); color:var(--g-text-secondary);
|
||||
}
|
||||
.mc-month-nav button:hover { border-color:var(--primary); color:var(--primary); }
|
||||
.mc-month-title { font-size:18px; font-weight:700; color:var(--g-text); min-width:140px; text-align:center; }
|
||||
.mc-legend { display:flex; gap:14px; font-size:12px; color:var(--g-text-secondary); }
|
||||
.mc-legend-item { display:flex; align-items:center; gap:4px; }
|
||||
.mc-legend-dot { width:10px; height:10px; border-radius:3px; }
|
||||
|
||||
/* 统计 */
|
||||
.mc-stats { display:grid; grid-template-columns:repeat(4,1fr); gap:12px; margin-bottom:16px; }
|
||||
.mc-stat-card {
|
||||
background:#fff; border-radius:10px; padding:14px 18px;
|
||||
box-shadow:var(--g-shadow-sm); transition:all var(--g-transition);
|
||||
}
|
||||
.mc-stat-card:hover { box-shadow:var(--g-shadow-md); transform:translateY(-1px); }
|
||||
.mc-stat-label { font-size:12px; color:var(--g-text-muted); margin-bottom:4px; }
|
||||
.mc-stat-value { font-size:20px; font-weight:700; color:var(--g-text); }
|
||||
.mc-stat-value.primary { color:var(--primary); }
|
||||
.mc-stat-value.orange { color:var(--g-warning); }
|
||||
.mc-stat-value.green { color:var(--g-success); }
|
||||
|
||||
/* 甘特图容器 */
|
||||
.mc-gantt {
|
||||
background:#fff; border-radius:10px; box-shadow:var(--g-shadow-sm); overflow:hidden;
|
||||
}
|
||||
|
||||
/* 日期头 */
|
||||
.mc-dates {
|
||||
display:grid; grid-template-columns:180px repeat(28, 1fr);
|
||||
border-bottom:1px solid #e5e7eb; background:#f8f9fb;
|
||||
}
|
||||
.mc-dates-label {
|
||||
padding:10px 16px; font-size:12px; font-weight:600; color:var(--g-text-secondary);
|
||||
border-right:1px solid #f0f0f0; display:flex; align-items:center;
|
||||
}
|
||||
.mc-date-cell {
|
||||
padding:8px 0; font-size:11px; color:var(--g-text-muted); text-align:center;
|
||||
border-right:1px solid #f5f5f5;
|
||||
}
|
||||
.mc-date-cell.today { background:color-mix(in srgb, var(--primary) 8%, #fff); color:var(--primary); font-weight:600; }
|
||||
.mc-date-cell.weekend { color:#ccc; }
|
||||
|
||||
/* 活动行 */
|
||||
.mc-row {
|
||||
display:grid; grid-template-columns:180px 1fr;
|
||||
border-bottom:1px solid #f5f5f5; min-height:44px; transition:background var(--g-transition);
|
||||
}
|
||||
.mc-row:hover { background:color-mix(in srgb, var(--primary) 2%, #fff); }
|
||||
.mc-row:last-child { border-bottom:none; }
|
||||
.mc-row-label {
|
||||
padding:10px 16px; font-size:13px; color:var(--g-text); display:flex;
|
||||
align-items:center; gap:8px; border-right:1px solid #f0f0f0;
|
||||
}
|
||||
.mc-row-label-name { font-weight:500; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
|
||||
.mc-type-dot { width:8px; height:8px; border-radius:2px; flex-shrink:0; }
|
||||
|
||||
/* 条形区域 */
|
||||
.mc-bar-area {
|
||||
position:relative; display:grid; grid-template-columns:repeat(28, 1fr); align-items:center;
|
||||
}
|
||||
.mc-bar {
|
||||
position:absolute; height:24px; border-radius:4px; top:50%; transform:translateY(-50%);
|
||||
font-size:11px; color:#fff; font-weight:500; display:flex; align-items:center;
|
||||
padding:0 8px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
|
||||
cursor:pointer; transition:filter var(--g-transition);
|
||||
}
|
||||
.mc-bar:hover { filter:brightness(1.1); }
|
||||
|
||||
/* 今日线 */
|
||||
.mc-today-line {
|
||||
position:absolute; top:0; bottom:0; width:2px; background:var(--g-danger);
|
||||
z-index:2; opacity:.6;
|
||||
}
|
||||
.mc-today-line::before {
|
||||
content:'今'; position:absolute; top:-18px; left:50%; transform:translateX(-50%);
|
||||
font-size:10px; color:var(--g-danger); font-weight:600;
|
||||
}
|
||||
|
||||
/* 冲突提示 */
|
||||
.mc-conflict-banner {
|
||||
display:flex; align-items:center; gap:8px; padding:10px 16px; margin-bottom:16px;
|
||||
background:#fff7ed; border:1px solid #fed7aa; border-radius:8px; font-size:13px; color:#9a3412;
|
||||
}
|
||||
|
||||
/* 空行提示 */
|
||||
.mc-empty-row {
|
||||
padding:40px; text-align:center; color:var(--g-text-muted); font-size:13px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="page-mc">
|
||||
|
||||
<!-- 冲突提示 -->
|
||||
<div class="mc-conflict-banner">
|
||||
<i data-lucide="alert-triangle" style="width:16px;height:16px;color:#f59e0b;flex-shrink:0;"></i>
|
||||
<span>2月10日~2月28日 有 <b>4个活动</b> 同时进行,请注意优惠叠加可能影响利润</span>
|
||||
</div>
|
||||
|
||||
<!-- 顶部控制栏 -->
|
||||
<div class="mc-header">
|
||||
<div class="mc-month-nav">
|
||||
<button><i data-lucide="chevron-left" style="width:16px;height:16px;"></i></button>
|
||||
<div class="mc-month-title">2026年 2月</div>
|
||||
<button><i data-lucide="chevron-right" style="width:16px;height:16px;"></i></button>
|
||||
</div>
|
||||
<div class="mc-legend">
|
||||
<span class="mc-legend-item"><span class="mc-legend-dot" style="background:#3b82f6;"></span>满减</span>
|
||||
<span class="mc-legend-item"><span class="mc-legend-dot" style="background:#22c55e;"></span>满赠</span>
|
||||
<span class="mc-legend-item"><span class="mc-legend-dot" style="background:#f59e0b;"></span>第二份半价</span>
|
||||
<span class="mc-legend-item"><span class="mc-legend-dot" style="background:#8b5cf6;"></span>限时折扣</span>
|
||||
<span class="mc-legend-item"><span class="mc-legend-dot" style="background:#ef4444;"></span>秒杀</span>
|
||||
<span class="mc-legend-item"><span class="mc-legend-dot" style="background:#ec4899;"></span>优惠券</span>
|
||||
<span class="mc-legend-item"><span class="mc-legend-dot" style="background:#06b6d4;"></span>次卡</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 统计 -->
|
||||
<div class="mc-stats">
|
||||
<div class="mc-stat-card">
|
||||
<div class="mc-stat-label">本月活动</div>
|
||||
<div class="mc-stat-value primary">8</div>
|
||||
</div>
|
||||
<div class="mc-stat-card">
|
||||
<div class="mc-stat-label">进行中</div>
|
||||
<div class="mc-stat-value green">6</div>
|
||||
</div>
|
||||
<div class="mc-stat-card">
|
||||
<div class="mc-stat-label">最大并行数</div>
|
||||
<div class="mc-stat-value orange">4</div>
|
||||
</div>
|
||||
<div class="mc-stat-card">
|
||||
<div class="mc-stat-label">本月预计优惠</div>
|
||||
<div class="mc-stat-value">¥6,200</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 甘特图 -->
|
||||
<div class="mc-gantt">
|
||||
<!-- 日期头 -->
|
||||
<div class="mc-dates">
|
||||
<div class="mc-dates-label">活动名称</div>
|
||||
<div class="mc-date-cell">1</div>
|
||||
<div class="mc-date-cell">2</div>
|
||||
<div class="mc-date-cell">3</div>
|
||||
<div class="mc-date-cell">4</div>
|
||||
<div class="mc-date-cell">5</div>
|
||||
<div class="mc-date-cell">6</div>
|
||||
<div class="mc-date-cell weekend">7</div>
|
||||
<div class="mc-date-cell weekend">8</div>
|
||||
<div class="mc-date-cell">9</div>
|
||||
<div class="mc-date-cell">10</div>
|
||||
<div class="mc-date-cell">11</div>
|
||||
<div class="mc-date-cell today">12</div>
|
||||
<div class="mc-date-cell">13</div>
|
||||
<div class="mc-date-cell weekend">14</div>
|
||||
<div class="mc-date-cell weekend">15</div>
|
||||
<div class="mc-date-cell">16</div>
|
||||
<div class="mc-date-cell">17</div>
|
||||
<div class="mc-date-cell">18</div>
|
||||
<div class="mc-date-cell">19</div>
|
||||
<div class="mc-date-cell">20</div>
|
||||
<div class="mc-date-cell weekend">21</div>
|
||||
<div class="mc-date-cell weekend">22</div>
|
||||
<div class="mc-date-cell">23</div>
|
||||
<div class="mc-date-cell">24</div>
|
||||
<div class="mc-date-cell">25</div>
|
||||
<div class="mc-date-cell">26</div>
|
||||
<div class="mc-date-cell">27</div>
|
||||
<div class="mc-date-cell weekend">28</div>
|
||||
</div>
|
||||
|
||||
<!-- 活动行 -->
|
||||
<!-- 1. 午市满减 1/1~3/31 全月覆盖 -->
|
||||
<div class="mc-row">
|
||||
<div class="mc-row-label">
|
||||
<span class="mc-type-dot" style="background:#3b82f6;"></span>
|
||||
<span class="mc-row-label-name">午市满减优惠</span>
|
||||
</div>
|
||||
<div class="mc-bar-area">
|
||||
<div class="mc-bar" style="left:0;right:0;background:#3b82f6;">满30减5 / 满50减10 / 满80减20</div>
|
||||
<div class="mc-today-line" style="left:calc((12 - 0.5) / 28 * 100%);"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 2. 晚市大额满减 1/15~4/15 全月覆盖 -->
|
||||
<div class="mc-row">
|
||||
<div class="mc-row-label">
|
||||
<span class="mc-type-dot" style="background:#3b82f6;"></span>
|
||||
<span class="mc-row-label-name">晚市大额满减</span>
|
||||
</div>
|
||||
<div class="mc-bar-area">
|
||||
<div class="mc-bar" style="left:0;right:0;background:#3b82f6;opacity:.75;">满50减8 / 满80减15 / 满120减30</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 3. 饮品买二赠一 2/1~3/31 全月覆盖 -->
|
||||
<div class="mc-row">
|
||||
<div class="mc-row-label">
|
||||
<span class="mc-type-dot" style="background:#22c55e;"></span>
|
||||
<span class="mc-row-label-name">饮品买二赠一</span>
|
||||
</div>
|
||||
<div class="mc-bar-area">
|
||||
<div class="mc-bar" style="left:0;right:0;background:#22c55e;">买2杯赠1杯</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 4. 甜品第二份半价 2/10~2/28 -->
|
||||
<div class="mc-row">
|
||||
<div class="mc-row-label">
|
||||
<span class="mc-type-dot" style="background:#f59e0b;"></span>
|
||||
<span class="mc-row-label-name">甜品第二份半价</span>
|
||||
</div>
|
||||
<div class="mc-bar-area">
|
||||
<div class="mc-bar" style="left:calc((10 - 1) / 28 * 100%);right:0;background:#f59e0b;">第2份5折</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 5. 疯狂星期四 限时折扣 每周四 -->
|
||||
<div class="mc-row">
|
||||
<div class="mc-row-label">
|
||||
<span class="mc-type-dot" style="background:#8b5cf6;"></span>
|
||||
<span class="mc-row-label-name">疯狂星期四</span>
|
||||
</div>
|
||||
<div class="mc-bar-area">
|
||||
<!-- 2/5, 2/12, 2/19, 2/26 are Thursdays -->
|
||||
<div class="mc-bar" style="left:calc((5 - 1) / 28 * 100%);width:calc(1 / 28 * 100%);background:#8b5cf6;border-radius:4px;font-size:0;"></div>
|
||||
<div class="mc-bar" style="left:calc((12 - 1) / 28 * 100%);width:calc(1 / 28 * 100%);background:#8b5cf6;border-radius:4px;font-size:0;"></div>
|
||||
<div class="mc-bar" style="left:calc((19 - 1) / 28 * 100%);width:calc(1 / 28 * 100%);background:#8b5cf6;border-radius:4px;font-size:0;"></div>
|
||||
<div class="mc-bar" style="left:calc((26 - 1) / 28 * 100%);width:calc(1 / 28 * 100%);background:#8b5cf6;border-radius:4px;font-size:0;"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 6. 情人节秒杀 2/13~2/14 -->
|
||||
<div class="mc-row">
|
||||
<div class="mc-row-label">
|
||||
<span class="mc-type-dot" style="background:#ef4444;"></span>
|
||||
<span class="mc-row-label-name">情人节秒杀</span>
|
||||
</div>
|
||||
<div class="mc-bar-area">
|
||||
<div class="mc-bar" style="left:calc((13 - 1) / 28 * 100%);width:calc(2 / 28 * 100%);background:#ef4444;">¥9.9 双人套餐</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 7. 新用户满减券 长期 -->
|
||||
<div class="mc-row">
|
||||
<div class="mc-row-label">
|
||||
<span class="mc-type-dot" style="background:#ec4899;"></span>
|
||||
<span class="mc-row-label-name">新用户满减券</span>
|
||||
</div>
|
||||
<div class="mc-bar-area">
|
||||
<div class="mc-bar" style="left:0;right:0;background:#ec4899;opacity:.65;">满50减15(长期)</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 8. 咖啡月卡 次卡 长期 -->
|
||||
<div class="mc-row">
|
||||
<div class="mc-row-label">
|
||||
<span class="mc-type-dot" style="background:#06b6d4;"></span>
|
||||
<span class="mc-row-label-name">咖啡月卡</span>
|
||||
</div>
|
||||
<div class="mc-bar-area">
|
||||
<div class="mc-bar" style="left:0;right:0;background:#06b6d4;opacity:.65;">¥99 / 30次(长期在售)</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
if (typeof lucide !== 'undefined') { lucide.createIcons(); }
|
||||
</script>
|
||||
678
pages/mkt-pass-card.html
Normal file
678
pages/mkt-pass-card.html
Normal file
@@ -0,0 +1,678 @@
|
||||
<!-- 次卡管理页 -->
|
||||
<style>
|
||||
.page-pk { max-width:1100px; }
|
||||
|
||||
/* 分段 Tab */
|
||||
.pk-seg { display:flex; background:#f5f5f5; border-radius:var(--g-radius); overflow:hidden; border:1px solid #e8e8e8; width:fit-content; margin-bottom:16px; }
|
||||
.pk-seg-item {
|
||||
padding:8px 28px; font-size:13px; cursor:pointer; color:var(--g-text-muted);
|
||||
transition:all var(--g-transition); user-select:none; border-right:1px solid #e8e8e8;
|
||||
background:transparent; border-top:none; border-bottom:none; border-left:none;
|
||||
}
|
||||
.pk-seg-item:last-child { border-right:none; }
|
||||
.pk-seg-item:hover { color:var(--g-text-secondary); background:#f0f0f0; }
|
||||
.pk-seg-item.active { background:#fff; color:var(--primary); font-weight:600; box-shadow:0 1px 4px rgba(0,0,0,.06); }
|
||||
|
||||
/* 统计卡片 */
|
||||
.pk-stats { display:grid; grid-template-columns:repeat(4,1fr); gap:12px; margin-bottom:16px; }
|
||||
.pk-stat-card {
|
||||
background:#fff; border-radius:10px; padding:16px 20px;
|
||||
box-shadow:var(--g-shadow-sm); transition:all var(--g-transition);
|
||||
}
|
||||
.pk-stat-card:hover { box-shadow:var(--g-shadow-md); transform:translateY(-1px); }
|
||||
.pk-stat-label { font-size:13px; color:var(--g-text-muted); margin-bottom:6px; }
|
||||
.pk-stat-value { font-size:24px; font-weight:700; color:var(--g-text); }
|
||||
.pk-stat-value.primary { color:var(--primary); }
|
||||
.pk-stat-value.green { color:var(--g-success); }
|
||||
.pk-stat-value.orange { color:var(--g-warning); }
|
||||
|
||||
/* 工具栏 */
|
||||
.pk-toolbar {
|
||||
display:flex; align-items:center; gap:12px; flex-wrap:wrap; margin-bottom:16px;
|
||||
box-shadow:var(--g-shadow-sm); border-radius:10px; padding:10px 14px; background:#fff;
|
||||
}
|
||||
.pk-toolbar select, .pk-toolbar input[type="text"] {
|
||||
height:34px; padding:0 10px; border:1px solid #e5e7eb; border-radius:8px;
|
||||
font-size:13px; outline:none; transition:all var(--g-transition); background:#fff;
|
||||
}
|
||||
.pk-toolbar select:focus, .pk-toolbar input[type="text"]:focus {
|
||||
border-color:var(--primary); box-shadow:0 0 0 3px color-mix(in srgb, var(--primary) 12%, transparent);
|
||||
}
|
||||
|
||||
/* 次卡网格 */
|
||||
.pk-grid { display:grid; grid-template-columns:repeat(2,1fr); gap:16px; margin-bottom:16px; }
|
||||
.pk-card {
|
||||
background:#fff; border-radius:12px; overflow:hidden;
|
||||
box-shadow:var(--g-shadow-sm); transition:all var(--g-transition); display:flex;
|
||||
}
|
||||
.pk-card:hover { box-shadow:var(--g-shadow-md); transform:translateY(-1px); }
|
||||
.pk-card.pk-off { opacity:.55; }
|
||||
.pk-card-cover {
|
||||
width:140px; min-height:160px; flex-shrink:0; display:flex; align-items:center; justify-content:center;
|
||||
color:#fff; font-size:28px; font-weight:700; position:relative;
|
||||
}
|
||||
.pk-card-cover .pk-cover-icon { opacity:.3; position:absolute; }
|
||||
.pk-card-cover-label { position:relative; z-index:1; text-align:center; line-height:1.3; }
|
||||
.pk-card-cover-label small { display:block; font-size:12px; font-weight:400; opacity:.8; }
|
||||
.pk-card-bd { flex:1; padding:16px; display:flex; flex-direction:column; }
|
||||
.pk-card-name { font-size:15px; font-weight:600; color:var(--g-text); margin-bottom:6px; display:flex; align-items:center; gap:6px; }
|
||||
.pk-card-price { margin-bottom:8px; display:flex; align-items:baseline; gap:6px; }
|
||||
.pk-card-price-now { font-size:22px; font-weight:700; color:var(--g-danger); }
|
||||
.pk-card-price-orig { font-size:13px; color:var(--g-text-muted); text-decoration:line-through; }
|
||||
.pk-card-info { display:flex; flex-wrap:wrap; gap:6px; margin-bottom:10px; }
|
||||
.pk-info-tag {
|
||||
font-size:11px; padding:2px 8px; border-radius:4px; background:#f5f5f5; color:var(--g-text-secondary);
|
||||
}
|
||||
.pk-card-meta { font-size:12px; color:var(--g-text-muted); margin-bottom:10px; display:flex; gap:14px; }
|
||||
.pk-card-ft { display:flex; align-items:center; gap:6px; margin-top:auto; padding-top:10px; border-top:1px solid #f5f5f5; }
|
||||
.pk-card-ft .g-tag { margin-left:auto; }
|
||||
|
||||
/* scope tag 颜色 */
|
||||
.pk-scope-tag { font-size:11px; font-weight:500; padding:1px 6px; border-radius:4px; }
|
||||
.pk-scope-tag.blue { background:color-mix(in srgb, var(--primary) 12%, #fff); color:var(--primary); }
|
||||
.pk-scope-tag.green { background:color-mix(in srgb, var(--g-success) 12%, #fff); color:var(--g-success); }
|
||||
.pk-scope-tag.orange { background:color-mix(in srgb, var(--g-warning) 12%, #fff); color:var(--g-warning); }
|
||||
.pk-scope-tag.purple { background:color-mix(in srgb, #7c3aed 12%, #fff); color:#7c3aed; }
|
||||
|
||||
/* 使用记录 */
|
||||
.pk-rec-member { display:flex; flex-direction:column; gap:2px; }
|
||||
.pk-rec-member-name { font-size:13px; font-weight:500; color:var(--g-text); }
|
||||
.pk-rec-member-phone { font-size:12px; color:var(--g-text-muted); }
|
||||
.pk-rec-status { display:inline-flex; align-items:center; gap:4px; font-size:12px; }
|
||||
.pk-rec-status::before { content:''; width:6px; height:6px; border-radius:50%; }
|
||||
.pk-rec-status.green::before { background:var(--g-success); }
|
||||
.pk-rec-status.orange::before { background:var(--g-warning); }
|
||||
.pk-rec-status.gray::before { background:#bbb; }
|
||||
|
||||
/* 抽屉内上传 */
|
||||
.pk-upload-placeholder {
|
||||
width:100%; height:100px; border:2px dashed #d9d9d9; border-radius:var(--g-radius);
|
||||
display:flex; flex-direction:column; align-items:center; justify-content:center;
|
||||
color:var(--g-text-muted); font-size:13px; gap:6px; cursor:pointer;
|
||||
transition:all var(--g-transition); background:var(--g-bg-subtle);
|
||||
}
|
||||
.pk-upload-placeholder:hover { border-color:var(--primary); color:var(--primary); background:color-mix(in srgb, var(--primary) 4%, #fff); }
|
||||
|
||||
/* 通知 pill 多选 */
|
||||
.pk-notify-pills { display:flex; gap:10px; }
|
||||
.pk-notify-pills .g-pill { position:relative; padding-left:24px; }
|
||||
.pk-notify-pills .g-pill::before {
|
||||
content:''; position:absolute; left:8px; top:50%; transform:translateY(-50%);
|
||||
width:12px; height:12px; border:1.5px solid #ccc; border-radius:3px; transition:all var(--g-transition);
|
||||
}
|
||||
.pk-notify-pills .g-pill.checked::before {
|
||||
background:var(--primary); border-color:var(--primary);
|
||||
background-image:url("data:image/svg+xml,%3Csvg viewBox='0 0 12 12' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M2.5 6L5 8.5L9.5 4' stroke='white' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
|
||||
}
|
||||
|
||||
/* section 标题 */
|
||||
.pk-section-hd {
|
||||
font-size:15px; font-weight:600; color:var(--g-text);
|
||||
padding-left:10px; border-left:3px solid var(--primary); margin-bottom:16px;
|
||||
}
|
||||
|
||||
/* 适用范围选中项 */
|
||||
.pk-scope-items { display:flex; flex-wrap:wrap; gap:6px; margin-top:8px; }
|
||||
.pk-scope-item {
|
||||
display:inline-flex; align-items:center; gap:4px; padding:4px 10px; background:#f5f5f5;
|
||||
border-radius:6px; font-size:12px; color:var(--g-text-secondary);
|
||||
}
|
||||
.pk-scope-item button {
|
||||
background:none; border:none; color:var(--g-text-muted); cursor:pointer; padding:0; line-height:1;
|
||||
}
|
||||
.pk-scope-item button:hover { color:var(--g-danger); }
|
||||
</style>
|
||||
|
||||
<div class="page-pk">
|
||||
<!-- 分段 Tab -->
|
||||
<div class="pk-seg">
|
||||
<button class="pk-seg-item active" onclick="switchPkTab(this, 'list')">次卡列表</button>
|
||||
<button class="pk-seg-item" onclick="switchPkTab(this, 'records')">使用记录</button>
|
||||
</div>
|
||||
|
||||
<!-- ==================== TAB 1: 次卡列表 ==================== -->
|
||||
<div id="pkTabList">
|
||||
|
||||
<!-- 统计 -->
|
||||
<div class="pk-stats">
|
||||
<div class="pk-stat-card">
|
||||
<div class="pk-stat-label">在售次卡</div>
|
||||
<div class="pk-stat-value primary">3</div>
|
||||
</div>
|
||||
<div class="pk-stat-card">
|
||||
<div class="pk-stat-label">累计售出</div>
|
||||
<div class="pk-stat-value">287张</div>
|
||||
</div>
|
||||
<div class="pk-stat-card">
|
||||
<div class="pk-stat-label">累计收入</div>
|
||||
<div class="pk-stat-value green">¥18,640</div>
|
||||
</div>
|
||||
<div class="pk-stat-card">
|
||||
<div class="pk-stat-label">使用中</div>
|
||||
<div class="pk-stat-value orange">124张</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 工具栏 -->
|
||||
<div class="pk-toolbar">
|
||||
<select style="width:120px;">
|
||||
<option value="">全部状态</option>
|
||||
<option>上架</option>
|
||||
<option>下架</option>
|
||||
</select>
|
||||
<input type="text" placeholder="搜索次卡名称" style="width:200px;">
|
||||
<div style="flex:1;"></div>
|
||||
<button class="g-btn g-btn-primary" onclick="openPkDrawer()">
|
||||
<i data-lucide="plus" style="width:14px;height:14px;"></i>创建次卡
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- 次卡网格 -->
|
||||
<div class="pk-grid">
|
||||
|
||||
<!-- 卡1: 咖啡月卡 -->
|
||||
<div class="pk-card">
|
||||
<div class="pk-card-cover" style="background:linear-gradient(135deg,#6366f1,#8b5cf6);">
|
||||
<i data-lucide="coffee" class="pk-cover-icon" style="width:60px;height:60px;"></i>
|
||||
<div class="pk-card-cover-label">30<small>次</small></div>
|
||||
</div>
|
||||
<div class="pk-card-bd">
|
||||
<div class="pk-card-name">咖啡月卡<span class="pk-scope-tag blue">指定分类</span></div>
|
||||
<div class="pk-card-price">
|
||||
<span class="pk-card-price-now">¥99</span>
|
||||
<span class="pk-card-price-orig">¥150</span>
|
||||
</div>
|
||||
<div class="pk-card-info">
|
||||
<span class="pk-info-tag">30天有效</span>
|
||||
<span class="pk-info-tag">完全免费</span>
|
||||
<span class="pk-info-tag">每日限1次</span>
|
||||
</div>
|
||||
<div class="pk-card-meta">
|
||||
<span>已售 156</span>
|
||||
<span>使用中 68</span>
|
||||
</div>
|
||||
<div class="pk-card-ft">
|
||||
<a class="g-action" onclick="openPkDrawer()">编辑</a>
|
||||
<a class="g-action">下架</a>
|
||||
<a class="g-action g-action-danger">删除</a>
|
||||
<span class="g-tag g-tag-green">上架</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 卡2: 早餐周卡 -->
|
||||
<div class="pk-card">
|
||||
<div class="pk-card-cover" style="background:linear-gradient(135deg,#f59e0b,#f97316);">
|
||||
<i data-lucide="sunrise" class="pk-cover-icon" style="width:60px;height:60px;"></i>
|
||||
<div class="pk-card-cover-label">7<small>次</small></div>
|
||||
</div>
|
||||
<div class="pk-card-bd">
|
||||
<div class="pk-card-name">早餐周卡<span class="pk-scope-tag green">指定标签</span></div>
|
||||
<div class="pk-card-price">
|
||||
<span class="pk-card-price-now">¥29</span>
|
||||
<span class="pk-card-price-orig">¥56</span>
|
||||
</div>
|
||||
<div class="pk-card-info">
|
||||
<span class="pk-info-tag">7天有效</span>
|
||||
<span class="pk-info-tag">完全免费</span>
|
||||
<span class="pk-info-tag">每日限1次</span>
|
||||
</div>
|
||||
<div class="pk-card-meta">
|
||||
<span>已售 89</span>
|
||||
<span>使用中 34</span>
|
||||
</div>
|
||||
<div class="pk-card-ft">
|
||||
<a class="g-action" onclick="openPkDrawer()">编辑</a>
|
||||
<a class="g-action">下架</a>
|
||||
<a class="g-action g-action-danger">删除</a>
|
||||
<span class="g-tag g-tag-green">上架</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 卡3: 奶茶畅饮卡 -->
|
||||
<div class="pk-card">
|
||||
<div class="pk-card-cover" style="background:linear-gradient(135deg,#ec4899,#f43f5e);">
|
||||
<i data-lucide="cup-soda" class="pk-cover-icon" style="width:60px;height:60px;"></i>
|
||||
<div class="pk-card-cover-label">15<small>次</small></div>
|
||||
</div>
|
||||
<div class="pk-card-bd">
|
||||
<div class="pk-card-name">奶茶畅饮卡<span class="pk-scope-tag purple">指定商品</span></div>
|
||||
<div class="pk-card-price">
|
||||
<span class="pk-card-price-now">¥59</span>
|
||||
<span class="pk-card-price-orig">¥120</span>
|
||||
</div>
|
||||
<div class="pk-card-info">
|
||||
<span class="pk-info-tag">15天有效</span>
|
||||
<span class="pk-info-tag">上限¥20/次</span>
|
||||
<span class="pk-info-tag">不限次/日</span>
|
||||
</div>
|
||||
<div class="pk-card-meta">
|
||||
<span>已售 42</span>
|
||||
<span>使用中 22</span>
|
||||
</div>
|
||||
<div class="pk-card-ft">
|
||||
<a class="g-action" onclick="openPkDrawer()">编辑</a>
|
||||
<a class="g-action">下架</a>
|
||||
<a class="g-action g-action-danger">删除</a>
|
||||
<span class="g-tag g-tag-green">上架</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 卡4: 午餐次卡(已下架) -->
|
||||
<div class="pk-card pk-off">
|
||||
<div class="pk-card-cover" style="background:linear-gradient(135deg,#64748b,#94a3af);">
|
||||
<i data-lucide="utensils" class="pk-cover-icon" style="width:60px;height:60px;"></i>
|
||||
<div class="pk-card-cover-label">20<small>次</small></div>
|
||||
</div>
|
||||
<div class="pk-card-bd">
|
||||
<div class="pk-card-name">午餐次卡<span class="pk-scope-tag blue">指定分类</span></div>
|
||||
<div class="pk-card-price">
|
||||
<span class="pk-card-price-now">¥199</span>
|
||||
<span class="pk-card-price-orig">¥300</span>
|
||||
</div>
|
||||
<div class="pk-card-info">
|
||||
<span class="pk-info-tag">30天有效</span>
|
||||
<span class="pk-info-tag">完全免费</span>
|
||||
<span class="pk-info-tag">每日限1次</span>
|
||||
</div>
|
||||
<div class="pk-card-meta">
|
||||
<span>已售 0</span>
|
||||
<span>使用中 0</span>
|
||||
</div>
|
||||
<div class="pk-card-ft">
|
||||
<a class="g-action" onclick="openPkDrawer()">编辑</a>
|
||||
<a class="g-action">上架</a>
|
||||
<a class="g-action g-action-danger">删除</a>
|
||||
<span class="g-tag g-tag-gray">下架</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ==================== TAB 2: 使用记录 ==================== -->
|
||||
<div id="pkTabRecords" style="display:none;">
|
||||
|
||||
<!-- 筛选工具栏 -->
|
||||
<div class="pk-toolbar">
|
||||
<select style="width:130px;">
|
||||
<option value="">全部次卡</option>
|
||||
<option>咖啡月卡</option>
|
||||
<option>早餐周卡</option>
|
||||
<option>奶茶畅饮卡</option>
|
||||
</select>
|
||||
<select style="width:120px;">
|
||||
<option value="">全部状态</option>
|
||||
<option>正常使用</option>
|
||||
<option>已用完</option>
|
||||
<option>已过期</option>
|
||||
</select>
|
||||
<input type="text" placeholder="搜索会员/商品" style="width:200px;">
|
||||
<div style="flex:1;"></div>
|
||||
<button class="g-btn g-btn-sm"><i data-lucide="download" style="width:13px;height:13px;"></i>导出</button>
|
||||
</div>
|
||||
|
||||
<!-- 统计 -->
|
||||
<div class="pk-stats" style="grid-template-columns:repeat(3,1fr);">
|
||||
<div class="pk-stat-card">
|
||||
<div class="pk-stat-label">今日使用</div>
|
||||
<div class="pk-stat-value primary">18</div>
|
||||
</div>
|
||||
<div class="pk-stat-card">
|
||||
<div class="pk-stat-label">本月使用</div>
|
||||
<div class="pk-stat-value">342</div>
|
||||
</div>
|
||||
<div class="pk-stat-card">
|
||||
<div class="pk-stat-label">即将过期(7天内)</div>
|
||||
<div class="pk-stat-value orange">15张</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 使用记录表格 -->
|
||||
<div class="g-card" style="padding:0;">
|
||||
<table class="g-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>使用单号</th>
|
||||
<th>会员</th>
|
||||
<th>次卡</th>
|
||||
<th>兑换商品</th>
|
||||
<th>使用时间</th>
|
||||
<th>剩余次数</th>
|
||||
<th>状态</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="font-family:monospace;font-size:12px;">PK20260212001</td>
|
||||
<td><div class="pk-rec-member"><span class="pk-rec-member-name">张三</span><span class="pk-rec-member-phone">138****6789</span></div></td>
|
||||
<td>咖啡月卡</td>
|
||||
<td>美式咖啡</td>
|
||||
<td style="font-size:12px;color:var(--g-text-secondary);">2026-02-12 08:30</td>
|
||||
<td><span style="font-weight:600;color:var(--primary);">22/30</span></td>
|
||||
<td><span class="pk-rec-status green">正常使用</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="font-family:monospace;font-size:12px;">PK20260212002</td>
|
||||
<td><div class="pk-rec-member"><span class="pk-rec-member-name">李四</span><span class="pk-rec-member-phone">139****1234</span></div></td>
|
||||
<td>早餐周卡</td>
|
||||
<td>鸡蛋灌饼</td>
|
||||
<td style="font-size:12px;color:var(--g-text-secondary);">2026-02-12 07:45</td>
|
||||
<td><span style="font-weight:600;color:var(--primary);">3/7</span></td>
|
||||
<td><span class="pk-rec-status green">正常使用</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="font-family:monospace;font-size:12px;">PK20260211003</td>
|
||||
<td><div class="pk-rec-member"><span class="pk-rec-member-name">王五</span><span class="pk-rec-member-phone">137****5678</span></div></td>
|
||||
<td>奶茶畅饮卡</td>
|
||||
<td>珍珠奶茶(补差价¥5)</td>
|
||||
<td style="font-size:12px;color:var(--g-text-secondary);">2026-02-11 15:20</td>
|
||||
<td><span style="font-weight:600;color:var(--g-warning);">2/15</span></td>
|
||||
<td><span class="pk-rec-status orange">即将用完</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="font-family:monospace;font-size:12px;">PK20260211004</td>
|
||||
<td><div class="pk-rec-member"><span class="pk-rec-member-name">赵六</span><span class="pk-rec-member-phone">136****4321</span></div></td>
|
||||
<td>咖啡月卡</td>
|
||||
<td>拿铁</td>
|
||||
<td style="font-size:12px;color:var(--g-text-secondary);">2026-02-11 09:10</td>
|
||||
<td><span style="font-weight:600;color:var(--g-text-muted);">0/30</span></td>
|
||||
<td><span class="pk-rec-status gray">已用完</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="font-family:monospace;font-size:12px;">PK20260210005</td>
|
||||
<td><div class="pk-rec-member"><span class="pk-rec-member-name">孙七</span><span class="pk-rec-member-phone">135****8765</span></div></td>
|
||||
<td>早餐周卡</td>
|
||||
<td>豆浆油条套餐</td>
|
||||
<td style="font-size:12px;color:var(--g-text-secondary);">2026-02-10 07:30</td>
|
||||
<td><span style="font-weight:600;color:var(--g-text-muted);">0/7</span></td>
|
||||
<td><span class="pk-rec-status gray">已过期</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="font-family:monospace;font-size:12px;">PK20260210006</td>
|
||||
<td><div class="pk-rec-member"><span class="pk-rec-member-name">周八</span><span class="pk-rec-member-phone">133****2222</span></div></td>
|
||||
<td>咖啡月卡</td>
|
||||
<td>卡布奇诺</td>
|
||||
<td style="font-size:12px;color:var(--g-text-secondary);">2026-02-10 10:45</td>
|
||||
<td><span style="font-weight:600;color:var(--primary);">15/30</span></td>
|
||||
<td><span class="pk-rec-status green">正常使用</span></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- 分页 -->
|
||||
<div class="g-pagination" style="margin-top:16px;">
|
||||
<button class="g-page-btn" disabled><i data-lucide="chevron-left" style="width:14px;height:14px;"></i></button>
|
||||
<button class="g-page-btn active">1</button>
|
||||
<button class="g-page-btn">2</button>
|
||||
<button class="g-page-btn">3</button>
|
||||
<button class="g-page-btn"><i data-lucide="chevron-right" style="width:14px;height:14px;"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ==================== 创建/编辑次卡抽屉 ==================== -->
|
||||
<div class="g-drawer-mask" id="pkDrawerMask" onclick="closePkDrawer()"></div>
|
||||
<div class="g-drawer" id="pkDrawer" style="width:520px;">
|
||||
<div class="g-drawer-hd">
|
||||
<span class="g-drawer-title">创建次卡</span>
|
||||
<button class="g-drawer-close" onclick="closePkDrawer()">×</button>
|
||||
</div>
|
||||
<div class="g-drawer-bd">
|
||||
|
||||
<!-- 次卡名称 -->
|
||||
<div class="g-form-group">
|
||||
<label class="g-form-label required">次卡名称</label>
|
||||
<input class="g-input" placeholder="如:咖啡月卡、早餐周卡">
|
||||
</div>
|
||||
|
||||
<!-- 封面图片 -->
|
||||
<div class="g-form-group">
|
||||
<label class="g-form-label">封面图片</label>
|
||||
<div class="pk-upload-placeholder">
|
||||
<i data-lucide="upload-cloud" style="width:24px;height:24px;"></i>
|
||||
<span>点击上传封面</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 价格 -->
|
||||
<div style="display:flex;gap:12px;">
|
||||
<div class="g-form-group" style="flex:1;">
|
||||
<label class="g-form-label required">售价</label>
|
||||
<input class="g-input" type="number" placeholder="如:99" min="0" step="0.01">
|
||||
</div>
|
||||
<div class="g-form-group" style="flex:1;">
|
||||
<label class="g-form-label">原价</label>
|
||||
<input class="g-input" type="number" placeholder="如:150(划线价)" min="0" step="0.01">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 总次数 -->
|
||||
<div class="g-form-group">
|
||||
<label class="g-form-label required">总次数</label>
|
||||
<input class="g-input" type="number" placeholder="如:30" min="1">
|
||||
<div class="g-hint">购买后可使用的总次数</div>
|
||||
</div>
|
||||
|
||||
<!-- 有效期 -->
|
||||
<div class="g-form-group">
|
||||
<label class="g-form-label required">有效期</label>
|
||||
<div style="display:flex;gap:10px;margin-bottom:8px;">
|
||||
<span class="g-pill checked" onclick="selectPkValidity(this,'days')">固定天数</span>
|
||||
<span class="g-pill" onclick="selectPkValidity(this,'range')">日期范围</span>
|
||||
</div>
|
||||
<div id="pkValidityDays">
|
||||
<div style="display:flex;align-items:center;gap:8px;">
|
||||
<span style="font-size:13px;color:var(--g-text-secondary);">购买后</span>
|
||||
<input class="g-input" type="number" placeholder="如:30" min="1" style="width:100px;">
|
||||
<span style="font-size:13px;color:var(--g-text-secondary);">天内有效</span>
|
||||
</div>
|
||||
</div>
|
||||
<div id="pkValidityRange" style="display:none;">
|
||||
<div style="display:flex;align-items:center;gap:8px;">
|
||||
<input class="g-input" type="date" style="width:160px;">
|
||||
<span style="font-size:13px;color:var(--g-text-secondary);">至</span>
|
||||
<input class="g-input" type="date" style="width:160px;">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="g-divider"></div>
|
||||
|
||||
<!-- 适用范围 -->
|
||||
<div class="g-form-group">
|
||||
<label class="g-form-label required">适用范围</label>
|
||||
<div style="display:flex;gap:10px;margin-bottom:8px;">
|
||||
<span class="g-pill checked" onclick="selectPkScope(this,'all')">全部商品</span>
|
||||
<span class="g-pill" onclick="selectPkScope(this,'category')">指定分类</span>
|
||||
<span class="g-pill" onclick="selectPkScope(this,'tag')">指定标签</span>
|
||||
<span class="g-pill" onclick="selectPkScope(this,'product')">指定商品</span>
|
||||
</div>
|
||||
<div id="pkScopeAll">
|
||||
<div class="g-hint">持卡可兑换店内任意商品</div>
|
||||
</div>
|
||||
<div id="pkScopeCategory" style="display:none;">
|
||||
<select class="g-select" style="width:100%;">
|
||||
<option value="">请选择商品分类</option>
|
||||
<option>热饮</option>
|
||||
<option>冷饮</option>
|
||||
<option>早餐</option>
|
||||
<option>午餐套餐</option>
|
||||
<option>小食甜点</option>
|
||||
</select>
|
||||
<div class="pk-scope-items">
|
||||
<span class="pk-scope-item">热饮 <button onclick="this.parentElement.remove()"><i data-lucide="x" style="width:12px;height:12px;"></i></button></span>
|
||||
<span class="pk-scope-item">冷饮 <button onclick="this.parentElement.remove()"><i data-lucide="x" style="width:12px;height:12px;"></i></button></span>
|
||||
</div>
|
||||
<div class="g-hint">可多选,持卡可兑换所选分类下的任意商品</div>
|
||||
</div>
|
||||
<div id="pkScopeTag" style="display:none;">
|
||||
<select class="g-select" style="width:100%;">
|
||||
<option value="">请选择商品标签</option>
|
||||
<option>早餐系列</option>
|
||||
<option>人气爆款</option>
|
||||
<option>新品上市</option>
|
||||
<option>轻食健康</option>
|
||||
</select>
|
||||
<div class="pk-scope-items">
|
||||
<span class="pk-scope-item">早餐系列 <button onclick="this.parentElement.remove()"><i data-lucide="x" style="width:12px;height:12px;"></i></button></span>
|
||||
</div>
|
||||
<div class="g-hint">可多选,持卡可兑换带有所选标签的商品</div>
|
||||
</div>
|
||||
<div id="pkScopeProduct" style="display:none;">
|
||||
<button class="g-btn g-btn-sm" onclick="openProductPicker({title:'选择适用商品',subtitle:'次卡管理',onConfirm:function(){}})"><i data-lucide="plus" style="width:13px;height:13px;"></i>选择商品</button>
|
||||
<div class="pk-scope-items">
|
||||
<span class="pk-scope-item">美式咖啡 <button onclick="this.parentElement.remove()"><i data-lucide="x" style="width:12px;height:12px;"></i></button></span>
|
||||
<span class="pk-scope-item">拿铁 <button onclick="this.parentElement.remove()"><i data-lucide="x" style="width:12px;height:12px;"></i></button></span>
|
||||
<span class="pk-scope-item">卡布奇诺 <button onclick="this.parentElement.remove()"><i data-lucide="x" style="width:12px;height:12px;"></i></button></span>
|
||||
</div>
|
||||
<div class="g-hint">可多选,持卡仅可兑换指定的商品</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 使用模式 -->
|
||||
<div class="g-form-group">
|
||||
<label class="g-form-label required">使用模式</label>
|
||||
<div style="display:flex;gap:10px;margin-bottom:8px;">
|
||||
<span class="g-pill checked" onclick="selectPkUsageMode(this,'free')">完全免费</span>
|
||||
<span class="g-pill" onclick="selectPkUsageMode(this,'cap')">金额上限</span>
|
||||
</div>
|
||||
<div id="pkModeFree">
|
||||
<div class="g-hint">每次使用免费兑换一件适用范围内的商品,不限原价</div>
|
||||
</div>
|
||||
<div id="pkModeCap" style="display:none;">
|
||||
<div style="display:flex;align-items:center;gap:8px;">
|
||||
<span style="font-size:13px;color:var(--g-text-secondary);">每次使用上限</span>
|
||||
<input class="g-input" type="number" placeholder="如:20" min="0" step="0.01" style="width:100px;">
|
||||
<span style="font-size:13px;color:var(--g-text-secondary);">元</span>
|
||||
</div>
|
||||
<div class="g-hint">超出上限部分由顾客补差价</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="g-divider"></div>
|
||||
|
||||
<!-- 使用规则 -->
|
||||
<div class="g-form-group">
|
||||
<label class="g-form-label">每日限用</label>
|
||||
<div style="display:flex;align-items:center;gap:8px;">
|
||||
<input class="g-input" type="number" placeholder="不限" min="0" style="width:100px;">
|
||||
<span style="font-size:13px;color:var(--g-text-secondary);">次/天</span>
|
||||
</div>
|
||||
<div class="g-hint">留空或填0表示不限制每日使用次数</div>
|
||||
</div>
|
||||
|
||||
<div class="g-form-group">
|
||||
<label class="g-form-label">每单限用</label>
|
||||
<div style="display:flex;align-items:center;gap:8px;">
|
||||
<input class="g-input" type="number" placeholder="不限" min="0" style="width:100px;">
|
||||
<span style="font-size:13px;color:var(--g-text-secondary);">次/单</span>
|
||||
</div>
|
||||
<div class="g-hint">同一订单内可使用的次数,如一单点5杯可用5次</div>
|
||||
</div>
|
||||
|
||||
<div class="g-form-group">
|
||||
<label class="g-form-label">每人限购</label>
|
||||
<div style="display:flex;align-items:center;gap:8px;">
|
||||
<input class="g-input" type="number" placeholder="不限" min="0" style="width:100px;">
|
||||
<span style="font-size:13px;color:var(--g-text-secondary);">张</span>
|
||||
</div>
|
||||
<div class="g-hint">留空或填0表示不限制购买数量</div>
|
||||
</div>
|
||||
|
||||
<div style="display:flex;gap:24px;margin-bottom:16px;">
|
||||
<div style="display:flex;align-items:center;gap:10px;">
|
||||
<span style="font-size:13px;color:var(--g-text);">允许转赠</span>
|
||||
<div class="g-toggle" onclick="toggleSwitch(this)"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 过期策略 -->
|
||||
<div class="g-form-group">
|
||||
<label class="g-form-label">过期策略</label>
|
||||
<div style="display:flex;gap:10px;">
|
||||
<span class="g-pill checked" onclick="this.parentElement.querySelectorAll('.g-pill').forEach(function(p){p.classList.remove('checked')});this.classList.add('checked')">剩余次数作废</span>
|
||||
<span class="g-pill" onclick="this.parentElement.querySelectorAll('.g-pill').forEach(function(p){p.classList.remove('checked')});this.classList.add('checked')">可申请退款</span>
|
||||
</div>
|
||||
<div class="g-hint">到期后未使用完的次数处理方式</div>
|
||||
</div>
|
||||
|
||||
<!-- 描述 -->
|
||||
<div class="g-form-group">
|
||||
<label class="g-form-label">次卡描述</label>
|
||||
<textarea class="g-textarea" rows="3" placeholder="请输入次卡说明,如使用规则、适用门店等"></textarea>
|
||||
</div>
|
||||
|
||||
<!-- 到账通知 -->
|
||||
<div class="g-form-group">
|
||||
<label class="g-form-label">购买通知</label>
|
||||
<div class="pk-notify-pills">
|
||||
<span class="g-pill checked" onclick="togglePill(this)">站内消息</span>
|
||||
<span class="g-pill" onclick="togglePill(this)">短信通知</span>
|
||||
</div>
|
||||
<div class="g-hint">顾客购买次卡后的通知方式</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="g-drawer-ft">
|
||||
<button class="g-btn" onclick="closePkDrawer()">取消</button>
|
||||
<button class="g-btn g-btn-primary">保存</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
/* Tab 切换 */
|
||||
function switchPkTab(el, tab) {
|
||||
document.querySelectorAll('.pk-seg-item').forEach(function(item) { item.classList.remove('active'); });
|
||||
el.classList.add('active');
|
||||
document.getElementById('pkTabList').style.display = tab === 'list' ? '' : 'none';
|
||||
document.getElementById('pkTabRecords').style.display = tab === 'records' ? '' : 'none';
|
||||
}
|
||||
|
||||
/* Toggle 开关 */
|
||||
function toggleSwitch(el) { el.classList.toggle('on'); }
|
||||
function togglePill(el) { el.classList.toggle('checked'); }
|
||||
|
||||
/* 有效期类型切换 */
|
||||
function selectPkValidity(el, type) {
|
||||
el.parentElement.querySelectorAll('.g-pill').forEach(function(p) { p.classList.remove('checked'); });
|
||||
el.classList.add('checked');
|
||||
document.getElementById('pkValidityDays').style.display = type === 'days' ? '' : 'none';
|
||||
document.getElementById('pkValidityRange').style.display = type === 'range' ? '' : 'none';
|
||||
}
|
||||
|
||||
/* 适用范围切换 */
|
||||
function selectPkScope(el, scope) {
|
||||
el.parentElement.querySelectorAll('.g-pill').forEach(function(p) { p.classList.remove('checked'); });
|
||||
el.classList.add('checked');
|
||||
document.getElementById('pkScopeAll').style.display = scope === 'all' ? '' : 'none';
|
||||
document.getElementById('pkScopeCategory').style.display = scope === 'category' ? '' : 'none';
|
||||
document.getElementById('pkScopeTag').style.display = scope === 'tag' ? '' : 'none';
|
||||
document.getElementById('pkScopeProduct').style.display = scope === 'product' ? '' : 'none';
|
||||
}
|
||||
|
||||
/* 使用模式切换 */
|
||||
function selectPkUsageMode(el, mode) {
|
||||
el.parentElement.querySelectorAll('.g-pill').forEach(function(p) { p.classList.remove('checked'); });
|
||||
el.classList.add('checked');
|
||||
document.getElementById('pkModeFree').style.display = mode === 'free' ? '' : 'none';
|
||||
document.getElementById('pkModeCap').style.display = mode === 'cap' ? '' : 'none';
|
||||
}
|
||||
|
||||
/* 抽屉开关 */
|
||||
function openPkDrawer() {
|
||||
document.getElementById('pkDrawerMask').classList.add('open');
|
||||
document.getElementById('pkDrawer').classList.add('open');
|
||||
}
|
||||
function closePkDrawer() {
|
||||
document.getElementById('pkDrawerMask').classList.remove('open');
|
||||
document.getElementById('pkDrawer').classList.remove('open');
|
||||
}
|
||||
|
||||
/* 初始化 Lucide 图标 */
|
||||
if (typeof lucide !== 'undefined') { lucide.createIcons(); }
|
||||
</script>
|
||||
@@ -97,6 +97,20 @@
|
||||
font-size:15px; font-weight:600; color:var(--g-text);
|
||||
padding-left:10px; border-left:3px solid var(--primary); margin-bottom:16px;
|
||||
}
|
||||
|
||||
/* 活动类型标签 */
|
||||
.fr-type-tag { font-size:11px; font-weight:500; padding:1px 6px; border-radius:4px; }
|
||||
.fr-type-tag.blue { background:color-mix(in srgb, var(--primary) 12%, #fff); color:var(--primary); }
|
||||
.fr-type-tag.green { background:color-mix(in srgb, var(--g-success) 12%, #fff); color:var(--g-success); }
|
||||
.fr-type-tag.orange { background:color-mix(in srgb, var(--g-warning) 12%, #fff); color:var(--g-warning); }
|
||||
|
||||
/* 满赠商品选择 */
|
||||
.fr-gift-item {
|
||||
display:inline-flex; align-items:center; gap:6px; padding:6px 10px;
|
||||
background:#f8f9fb; border-radius:6px; font-size:12px; color:var(--g-text-secondary); border:1px solid #e5e7eb;
|
||||
}
|
||||
.fr-gift-item button { background:none; border:none; color:var(--g-text-muted); cursor:pointer; padding:0; }
|
||||
.fr-gift-item button:hover { color:var(--g-danger); }
|
||||
</style>
|
||||
|
||||
<div class="page-fr">
|
||||
@@ -110,6 +124,12 @@
|
||||
<option>老三家外卖(通州店)</option>
|
||||
<option>老三家外卖(丰台店)</option>
|
||||
</select>
|
||||
<select style="width:130px;">
|
||||
<option value="">全部类型</option>
|
||||
<option>满减</option>
|
||||
<option>满赠</option>
|
||||
<option>第二份半价</option>
|
||||
</select>
|
||||
<select style="width:130px;">
|
||||
<option value="">全部状态</option>
|
||||
<option>进行中</option>
|
||||
@@ -119,7 +139,7 @@
|
||||
<input type="text" placeholder="搜索活动名称" style="width:200px;" />
|
||||
<div style="flex:1;"></div>
|
||||
<button class="g-btn g-btn-primary" onclick="openFrDrawer('create')">
|
||||
<i data-lucide="plus" style="width:14px;height:14px;"></i>创建满减活动
|
||||
<i data-lucide="plus" style="width:14px;height:14px;"></i>创建活动
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -150,6 +170,7 @@
|
||||
<div class="fr-card">
|
||||
<div class="fr-card-hd">
|
||||
<span class="fr-card-name">午市满减优惠</span>
|
||||
<span class="fr-type-tag blue">满减</span>
|
||||
<span class="g-tag g-tag-green">进行中</span>
|
||||
</div>
|
||||
<div class="fr-tiers">
|
||||
@@ -180,6 +201,7 @@
|
||||
<div class="fr-card">
|
||||
<div class="fr-card-hd">
|
||||
<span class="fr-card-name">晚市大额满减</span>
|
||||
<span class="fr-type-tag blue">满减</span>
|
||||
<span class="g-tag g-tag-green">进行中</span>
|
||||
</div>
|
||||
<div class="fr-tiers">
|
||||
@@ -210,6 +232,7 @@
|
||||
<div class="fr-card">
|
||||
<div class="fr-card-hd">
|
||||
<span class="fr-card-name">春季新客满减</span>
|
||||
<span class="fr-type-tag blue">满减</span>
|
||||
<span class="g-tag g-tag-blue">未开始</span>
|
||||
</div>
|
||||
<div class="fr-tiers">
|
||||
@@ -240,6 +263,7 @@
|
||||
<div class="fr-card fr-ended">
|
||||
<div class="fr-card-hd">
|
||||
<span class="fr-card-name">元旦满减狂欢</span>
|
||||
<span class="fr-type-tag blue">满减</span>
|
||||
<span class="g-tag g-tag-gray">已结束</span>
|
||||
</div>
|
||||
<div class="fr-tiers">
|
||||
@@ -265,6 +289,62 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 活动5:满赠 进行中 -->
|
||||
<div class="fr-card">
|
||||
<div class="fr-card-hd">
|
||||
<span class="fr-card-name">饮品买二赠一</span>
|
||||
<span class="fr-type-tag green">满赠</span>
|
||||
<span class="g-tag g-tag-green">进行中</span>
|
||||
</div>
|
||||
<div class="fr-tiers">
|
||||
<span class="fr-tier-pill">买2杯赠1杯</span>
|
||||
</div>
|
||||
<div class="fr-meta">
|
||||
<span class="fr-meta-item"><i data-lucide="calendar" style="width:14px;height:14px;"></i>2026-02-01 ~ 2026-03-31</span>
|
||||
<span class="fr-meta-item"><i data-lucide="truck" style="width:14px;height:14px;"></i>外卖 / 自提 / 堂食</span>
|
||||
<span class="fr-meta-item"><i data-lucide="store" style="width:14px;height:14px;"></i>全部门店</span>
|
||||
<span class="fr-meta-item"><i data-lucide="gift" style="width:14px;height:14px;"></i>赠品:指定饮品(价低者)</span>
|
||||
</div>
|
||||
<div class="fr-data">
|
||||
<span class="fr-data-item">参与订单 <span>98单</span></span>
|
||||
<span class="fr-data-item">赠出商品 <span>98件</span></span>
|
||||
<span class="fr-data-item">带动销售 <span>¥4,120</span></span>
|
||||
</div>
|
||||
<div class="fr-card-ft">
|
||||
<a class="g-action" onclick="openFrDrawer('edit')">编辑</a>
|
||||
<a class="g-action">停用</a>
|
||||
<a class="g-action g-action-danger">删除</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 活动6:第二份半价 进行中 -->
|
||||
<div class="fr-card">
|
||||
<div class="fr-card-hd">
|
||||
<span class="fr-card-name">甜品第二份半价</span>
|
||||
<span class="fr-type-tag orange">第二份半价</span>
|
||||
<span class="g-tag g-tag-green">进行中</span>
|
||||
</div>
|
||||
<div class="fr-tiers">
|
||||
<span class="fr-tier-pill">第2份5折</span>
|
||||
</div>
|
||||
<div class="fr-meta">
|
||||
<span class="fr-meta-item"><i data-lucide="calendar" style="width:14px;height:14px;"></i>2026-02-10 ~ 2026-02-28</span>
|
||||
<span class="fr-meta-item"><i data-lucide="truck" style="width:14px;height:14px;"></i>外卖 / 堂食</span>
|
||||
<span class="fr-meta-item"><i data-lucide="store" style="width:14px;height:14px;"></i>全部门店</span>
|
||||
<span class="fr-meta-item"><i data-lucide="tag" style="width:14px;height:14px;"></i>适用:甜品分类</span>
|
||||
</div>
|
||||
<div class="fr-data">
|
||||
<span class="fr-data-item">参与订单 <span>45单</span></span>
|
||||
<span class="fr-data-item">优惠总额 <span>¥380</span></span>
|
||||
<span class="fr-data-item">连带率提升 <span>32%</span></span>
|
||||
</div>
|
||||
<div class="fr-card-ft">
|
||||
<a class="g-action" onclick="openFrDrawer('edit')">编辑</a>
|
||||
<a class="g-action">停用</a>
|
||||
<a class="g-action g-action-danger">删除</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- 分页 -->
|
||||
@@ -286,43 +366,115 @@
|
||||
<button class="g-drawer-close" onclick="closeFrDrawer()"><i data-lucide="x" style="width:18px;height:18px;"></i></button>
|
||||
</div>
|
||||
<div class="g-drawer-bd">
|
||||
<!-- 活动类型 -->
|
||||
<div class="g-form-group">
|
||||
<label class="g-form-label required">活动类型</label>
|
||||
<div style="display:flex;gap:10px;">
|
||||
<span class="g-pill checked" onclick="selectFrType(this,'reduce')">满减</span>
|
||||
<span class="g-pill" onclick="selectFrType(this,'gift')">满赠</span>
|
||||
<span class="g-pill" onclick="selectFrType(this,'half')">第二份半价</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 活动名称 -->
|
||||
<div class="g-form-group">
|
||||
<label class="g-form-label required">活动名称</label>
|
||||
<input class="g-input" placeholder="如:午市满减优惠" />
|
||||
</div>
|
||||
|
||||
<!-- 满减规则 -->
|
||||
<div class="fr-section-hd" style="margin-top:8px;">满减规则</div>
|
||||
<div id="frTierList">
|
||||
<div class="fr-tier-row">
|
||||
<span>满</span>
|
||||
<input type="number" value="30" placeholder="金额" />
|
||||
<span>元减</span>
|
||||
<input type="number" value="5" placeholder="金额" />
|
||||
<span>元</span>
|
||||
<button class="fr-tier-del" onclick="removeFrTier(this)" title="删除"><i data-lucide="trash-2" style="width:14px;height:14px;"></i></button>
|
||||
<!-- ===== 满减规则 ===== -->
|
||||
<div id="frRuleReduce">
|
||||
<div class="fr-section-hd" style="margin-top:8px;">满减规则</div>
|
||||
<div id="frTierList">
|
||||
<div class="fr-tier-row">
|
||||
<span>满</span>
|
||||
<input type="number" value="30" placeholder="金额" />
|
||||
<span>元减</span>
|
||||
<input type="number" value="5" placeholder="金额" />
|
||||
<span>元</span>
|
||||
<button class="fr-tier-del" onclick="removeFrTier(this)" title="删除"><i data-lucide="trash-2" style="width:14px;height:14px;"></i></button>
|
||||
</div>
|
||||
<div class="fr-tier-row">
|
||||
<span>满</span>
|
||||
<input type="number" value="50" placeholder="金额" />
|
||||
<span>元减</span>
|
||||
<input type="number" value="10" placeholder="金额" />
|
||||
<span>元</span>
|
||||
<button class="fr-tier-del" onclick="removeFrTier(this)" title="删除"><i data-lucide="trash-2" style="width:14px;height:14px;"></i></button>
|
||||
</div>
|
||||
<div class="fr-tier-row">
|
||||
<span>满</span>
|
||||
<input type="number" value="80" placeholder="金额" />
|
||||
<span>元减</span>
|
||||
<input type="number" value="20" placeholder="金额" />
|
||||
<span>元</span>
|
||||
<button class="fr-tier-del" onclick="removeFrTier(this)" title="删除"><i data-lucide="trash-2" style="width:14px;height:14px;"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fr-tier-row">
|
||||
<span>满</span>
|
||||
<input type="number" value="50" placeholder="金额" />
|
||||
<span>元减</span>
|
||||
<input type="number" value="10" placeholder="金额" />
|
||||
<span>元</span>
|
||||
<button class="fr-tier-del" onclick="removeFrTier(this)" title="删除"><i data-lucide="trash-2" style="width:14px;height:14px;"></i></button>
|
||||
<button class="fr-add-tier" onclick="addFrTier()">
|
||||
<i data-lucide="plus" style="width:14px;height:14px;"></i>添加阶梯
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- ===== 满赠规则 ===== -->
|
||||
<div id="frRuleGift" style="display:none;">
|
||||
<div class="fr-section-hd" style="margin-top:8px;">满赠规则</div>
|
||||
<div class="g-form-group">
|
||||
<label class="g-form-label required">赠送条件</label>
|
||||
<div style="display:flex;align-items:center;gap:8px;font-size:13px;color:var(--g-text);">
|
||||
<span>购买满</span>
|
||||
<input class="g-input" type="number" value="2" min="1" style="width:70px;text-align:center;" placeholder="如:2">
|
||||
<span>件赠</span>
|
||||
<input class="g-input" type="number" value="1" min="1" style="width:70px;text-align:center;" placeholder="如:1">
|
||||
<span>件</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fr-tier-row">
|
||||
<span>满</span>
|
||||
<input type="number" value="80" placeholder="金额" />
|
||||
<span>元减</span>
|
||||
<input type="number" value="20" placeholder="金额" />
|
||||
<span>元</span>
|
||||
<button class="fr-tier-del" onclick="removeFrTier(this)" title="删除"><i data-lucide="trash-2" style="width:14px;height:14px;"></i></button>
|
||||
<div class="g-form-group">
|
||||
<label class="g-form-label required">赠品范围</label>
|
||||
<div style="display:flex;gap:10px;margin-bottom:8px;">
|
||||
<span class="g-pill checked" onclick="this.parentElement.querySelectorAll('.g-pill').forEach(function(p){p.classList.remove('checked')});this.classList.add('checked')">同商品(价低者)</span>
|
||||
<span class="g-pill" onclick="this.parentElement.querySelectorAll('.g-pill').forEach(function(p){p.classList.remove('checked')});this.classList.add('checked')">指定赠品</span>
|
||||
</div>
|
||||
<div class="g-hint">选"同商品"时,赠品为购买商品中价格最低的一件</div>
|
||||
</div>
|
||||
<div class="g-form-group">
|
||||
<label class="g-form-label">适用商品</label>
|
||||
<button class="g-btn g-btn-sm" onclick="openProductPicker({title:'选择适用商品',subtitle:'满赠活动',onConfirm:function(){}})"><i data-lucide="plus" style="width:13px;height:13px;"></i>选择商品/分类</button>
|
||||
<div style="display:flex;flex-wrap:wrap;gap:6px;margin-top:8px;">
|
||||
<span class="fr-gift-item">热饮分类 <button onclick="this.parentElement.remove()"><i data-lucide="x" style="width:12px;height:12px;"></i></button></span>
|
||||
<span class="fr-gift-item">冷饮分类 <button onclick="this.parentElement.remove()"><i data-lucide="x" style="width:12px;height:12px;"></i></button></span>
|
||||
</div>
|
||||
<div class="g-hint">留空表示全部商品参与</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ===== 第二份半价规则 ===== -->
|
||||
<div id="frRuleHalf" style="display:none;">
|
||||
<div class="fr-section-hd" style="margin-top:8px;">第二份优惠</div>
|
||||
<div class="g-form-group">
|
||||
<label class="g-form-label required">第二份折扣</label>
|
||||
<div style="display:flex;gap:10px;">
|
||||
<span class="g-pill checked" onclick="this.parentElement.querySelectorAll('.g-pill').forEach(function(p){p.classList.remove('checked')});this.classList.add('checked')">5折</span>
|
||||
<span class="g-pill" onclick="this.parentElement.querySelectorAll('.g-pill').forEach(function(p){p.classList.remove('checked')});this.classList.add('checked')">6折</span>
|
||||
<span class="g-pill" onclick="this.parentElement.querySelectorAll('.g-pill').forEach(function(p){p.classList.remove('checked')});this.classList.add('checked')">7折</span>
|
||||
<span class="g-pill" onclick="this.parentElement.querySelectorAll('.g-pill').forEach(function(p){p.classList.remove('checked')});this.classList.add('checked')">免费</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="g-form-group">
|
||||
<label class="g-form-label required">适用商品</label>
|
||||
<div style="display:flex;gap:10px;margin-bottom:8px;">
|
||||
<span class="g-pill checked" onclick="this.parentElement.querySelectorAll('.g-pill').forEach(function(p){p.classList.remove('checked')});this.classList.add('checked')">指定分类</span>
|
||||
<span class="g-pill" onclick="this.parentElement.querySelectorAll('.g-pill').forEach(function(p){p.classList.remove('checked')});this.classList.add('checked')">指定商品</span>
|
||||
</div>
|
||||
<select class="g-select" style="width:100%;">
|
||||
<option value="">请选择分类</option>
|
||||
<option>甜品</option>
|
||||
<option>饮品</option>
|
||||
<option>小食</option>
|
||||
</select>
|
||||
<div class="g-hint">第二份优惠仅适用于所选范围内的商品</div>
|
||||
</div>
|
||||
</div>
|
||||
<button class="fr-add-tier" onclick="addFrTier()">
|
||||
<i data-lucide="plus" style="width:14px;height:14px;"></i>添加阶梯
|
||||
</button>
|
||||
|
||||
<!-- 活动时间 -->
|
||||
<div class="g-form-group" style="margin-top:20px;">
|
||||
@@ -383,13 +535,22 @@
|
||||
function openFrDrawer(mode) {
|
||||
document.getElementById('frDrawerMask').classList.add('open');
|
||||
document.getElementById('frDrawer').classList.add('open');
|
||||
document.getElementById('frDrawerTitle').textContent = mode === 'edit' ? '编辑满减活动' : '创建满减活动';
|
||||
document.getElementById('frDrawerTitle').textContent = mode === 'edit' ? '编辑活动' : '创建活动';
|
||||
}
|
||||
function closeFrDrawer() {
|
||||
document.getElementById('frDrawerMask').classList.remove('open');
|
||||
document.getElementById('frDrawer').classList.remove('open');
|
||||
}
|
||||
|
||||
/* 活动类型切换 */
|
||||
function selectFrType(el, type) {
|
||||
el.parentElement.querySelectorAll('.g-pill').forEach(function(p) { p.classList.remove('checked'); });
|
||||
el.classList.add('checked');
|
||||
document.getElementById('frRuleReduce').style.display = type === 'reduce' ? '' : 'none';
|
||||
document.getElementById('frRuleGift').style.display = type === 'gift' ? '' : 'none';
|
||||
document.getElementById('frRuleHalf').style.display = type === 'half' ? '' : 'none';
|
||||
}
|
||||
|
||||
/* 添加阶梯行 */
|
||||
function addFrTier() {
|
||||
var list = document.getElementById('frTierList');
|
||||
|
||||
Reference in New Issue
Block a user