772 lines
36 KiB
HTML
772 lines
36 KiB
HTML
<!-- 积分商城页 -->
|
||
<style>
|
||
.page-pt { max-width:1100px; }
|
||
|
||
/* 分段 Tab */
|
||
.pt-seg { display:flex; background:#f5f5f5; border-radius:var(--g-radius); overflow:hidden; border:1px solid #e8e8e8; width:fit-content; margin-bottom:16px; }
|
||
.pt-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;
|
||
}
|
||
.pt-seg-item:last-child { border-right:none; }
|
||
.pt-seg-item:hover { color:var(--g-text-secondary); background:#f0f0f0; }
|
||
.pt-seg-item.active { background:#fff; color:var(--primary); font-weight:600; box-shadow:0 1px 4px rgba(0,0,0,.06); }
|
||
|
||
/* 统计卡片 */
|
||
.pt-stats { display:grid; grid-template-columns:repeat(4,1fr); gap:12px; margin-bottom:16px; }
|
||
.pt-stat-card {
|
||
background:#fff; border-radius:10px; padding:16px 20px;
|
||
box-shadow:var(--g-shadow-sm); transition:all var(--g-transition);
|
||
}
|
||
.pt-stat-card:hover { box-shadow:var(--g-shadow-md); transform:translateY(-1px); }
|
||
.pt-stat-label { font-size:13px; color:var(--g-text-muted); margin-bottom:6px; }
|
||
.pt-stat-value { font-size:24px; font-weight:700; color:var(--g-text); }
|
||
.pt-stat-value.primary { color:var(--primary); }
|
||
.pt-stat-value.green { color:var(--g-success); }
|
||
.pt-stat-value.orange { color:var(--g-warning); }
|
||
|
||
/* 规则卡片 section 标题 */
|
||
.pt-section-hd {
|
||
font-size:15px; font-weight:600; color:var(--g-text);
|
||
padding-left:10px; border-left:3px solid var(--primary); margin-bottom:16px;
|
||
}
|
||
|
||
/* 规则行 */
|
||
.pt-rule-row {
|
||
display:flex; align-items:center; gap:12px; padding:14px 0;
|
||
border-bottom:1px solid #f5f5f5; font-size:13px; color:var(--g-text);
|
||
}
|
||
.pt-rule-row:last-child { border-bottom:none; }
|
||
.pt-rule-row .g-toggle { flex-shrink:0; }
|
||
.pt-rule-label { min-width:110px; font-weight:500; flex-shrink:0; }
|
||
.pt-rule-row input[type="number"] {
|
||
width:70px; height:32px; padding:0 8px; border:1px solid #d9d9d9; border-radius:var(--g-radius-sm);
|
||
font-size:13px; outline:none; text-align:center; transition:all var(--g-transition);
|
||
}
|
||
.pt-rule-row input[type="number"]:focus { border-color:var(--primary); box-shadow:0 0 0 3px color-mix(in srgb, var(--primary) 10%, transparent); }
|
||
.pt-rule-text { color:var(--g-text-secondary); }
|
||
|
||
/* 有效期 pill */
|
||
.pt-expiry-pills { display:flex; gap:10px; margin-bottom:12px; }
|
||
|
||
/* 工具栏 */
|
||
.pt-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;
|
||
}
|
||
.pt-toolbar select,
|
||
.pt-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;
|
||
}
|
||
.pt-toolbar select:focus,
|
||
.pt-toolbar input[type="text"]:focus { border-color:var(--primary); box-shadow:0 0 0 3px color-mix(in srgb, var(--primary) 12%, transparent); }
|
||
|
||
/* 商品网格 */
|
||
.pt-grid { display:grid; grid-template-columns:repeat(3,1fr); gap:16px; margin-bottom:16px; }
|
||
.pt-prod-card {
|
||
background:#fff; border-radius:10px; overflow:hidden;
|
||
box-shadow:var(--g-shadow-sm); transition:all var(--g-transition);
|
||
}
|
||
.pt-prod-card:hover { box-shadow:var(--g-shadow-md); transform:translateY(-1px); }
|
||
.pt-prod-card.pt-off { opacity:.55; }
|
||
.pt-prod-img {
|
||
width:100%; height:120px; background:#f0f0f0; display:flex;
|
||
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; 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; }
|
||
.pt-prod-ft {
|
||
display:flex; align-items:center; gap:6px; padding-top:10px;
|
||
border-top:1px solid #f5f5f5;
|
||
}
|
||
.pt-prod-ft .g-tag { margin-left:auto; }
|
||
|
||
/* 抽屉内上传占位 */
|
||
.pt-upload-placeholder {
|
||
width:100%; height:120px; 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);
|
||
}
|
||
.pt-upload-placeholder:hover { border-color:var(--primary); color:var(--primary); background:color-mix(in srgb, var(--primary) 4%, #fff); }
|
||
|
||
/* 兑换方式 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>
|
||
|
||
<div class="page-pt">
|
||
<!-- 分段 Tab -->
|
||
<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: 积分规则 ==================== -->
|
||
<div id="ptTabRules">
|
||
|
||
<!-- 统计卡片 -->
|
||
<div class="pt-stats">
|
||
<div class="pt-stat-card">
|
||
<div class="pt-stat-label">累计发放积分</div>
|
||
<div class="pt-stat-value primary">128,600</div>
|
||
</div>
|
||
<div class="pt-stat-card">
|
||
<div class="pt-stat-label">已兑换积分</div>
|
||
<div class="pt-stat-value orange">45,200</div>
|
||
</div>
|
||
<div class="pt-stat-card">
|
||
<div class="pt-stat-label">积分用户</div>
|
||
<div class="pt-stat-value">856人</div>
|
||
</div>
|
||
<div class="pt-stat-card">
|
||
<div class="pt-stat-label">兑换率</div>
|
||
<div class="pt-stat-value green">35.1%</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 积分获取规则 -->
|
||
<div class="g-card" style="margin-bottom:16px;">
|
||
<div class="pt-section-hd">积分获取规则</div>
|
||
|
||
<div class="pt-rule-row">
|
||
<div class="g-toggle on" onclick="toggleSwitch(this)"></div>
|
||
<span class="pt-rule-label">消费获取</span>
|
||
<span class="pt-rule-text">每消费</span>
|
||
<input type="number" value="1" min="0" placeholder="如:1">
|
||
<span class="pt-rule-text">元获得</span>
|
||
<input type="number" value="1" min="0" placeholder="如:1">
|
||
<span class="pt-rule-text">积分</span>
|
||
</div>
|
||
|
||
<div class="pt-rule-row">
|
||
<div class="g-toggle on" onclick="toggleSwitch(this)"></div>
|
||
<span class="pt-rule-label">评价奖励</span>
|
||
<span class="pt-rule-text">发表评价奖励</span>
|
||
<input type="number" value="10" min="0" placeholder="如:10">
|
||
<span class="pt-rule-text">积分</span>
|
||
</div>
|
||
|
||
<div class="pt-rule-row">
|
||
<div class="g-toggle on" onclick="toggleSwitch(this)"></div>
|
||
<span class="pt-rule-label">注册奖励</span>
|
||
<span class="pt-rule-text">新用户注册赠送</span>
|
||
<input type="number" value="100" min="0" placeholder="如:100">
|
||
<span class="pt-rule-text">积分</span>
|
||
</div>
|
||
|
||
<div class="pt-rule-row">
|
||
<div class="g-toggle" onclick="toggleSwitch(this)"></div>
|
||
<span class="pt-rule-label">签到奖励</span>
|
||
<span class="pt-rule-text">每日签到奖励</span>
|
||
<input type="number" value="5" min="0" placeholder="如:5">
|
||
<span class="pt-rule-text">积分</span>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 积分有效期 -->
|
||
<div class="g-card" style="margin-bottom:16px;">
|
||
<div class="pt-section-hd">积分有效期</div>
|
||
|
||
<div class="pt-expiry-pills">
|
||
<span class="g-pill" onclick="selectPtExpiry(this)">永久有效</span>
|
||
<span class="g-pill checked" onclick="selectPtExpiry(this)">按年清零</span>
|
||
</div>
|
||
<div class="g-hint" id="ptExpiryHint">每年12月31日清零当年获得的积分,请提前通知会员</div>
|
||
</div>
|
||
|
||
<!-- 保存按钮 -->
|
||
<div class="pt-save-bar">
|
||
<button class="g-btn g-btn-primary g-btn-lg">
|
||
<i data-lucide="save" style="width:15px;height:15px;"></i>保存规则
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ==================== TAB 2: 兑换商品 ==================== -->
|
||
<div id="ptTabProducts" style="display:none;">
|
||
|
||
<!-- 工具栏 -->
|
||
<div class="pt-toolbar">
|
||
<select style="width:130px;">
|
||
<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="openPtDrawer()">
|
||
<i data-lucide="plus" style="width:14px;height:14px;"></i>添加兑换商品
|
||
</button>
|
||
</div>
|
||
|
||
<!-- 商品网格 -->
|
||
<div class="pt-grid">
|
||
|
||
<!-- 商品1 -->
|
||
<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">可乐兑换券<span class="pt-type-tag blue">商品</span></div>
|
||
<div class="pt-prod-price">100积分</div>
|
||
<div class="pt-prod-meta">
|
||
<span>库存 50</span>
|
||
<span>已兑换 28</span>
|
||
</div>
|
||
<div class="pt-prod-ft">
|
||
<a class="g-action" onclick="openPtDrawer()">编辑</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="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">凉拌黄瓜<span class="pt-type-tag blue">商品</span></div>
|
||
<div class="pt-prod-price">200积分</div>
|
||
<div class="pt-prod-meta">
|
||
<span>库存 30</span>
|
||
<span>已兑换 45</span>
|
||
</div>
|
||
<div class="pt-prod-ft">
|
||
<a class="g-action" onclick="openPtDrawer()">编辑</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="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券<span class="pt-type-tag green">优惠券</span></div>
|
||
<div class="pt-prod-price">300积分</div>
|
||
<div class="pt-prod-meta">
|
||
<span>库存 100</span>
|
||
<span>已兑换 67</span>
|
||
</div>
|
||
<div class="pt-prod-ft">
|
||
<a class="g-action" onclick="openPtDrawer()">编辑</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="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">招牌奶茶<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>
|
||
<span>已兑换 12</span>
|
||
</div>
|
||
<div class="pt-prod-ft">
|
||
<a class="g-action" onclick="openPtDrawer()">编辑</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>
|
||
|
||
<!-- 商品5 -->
|
||
<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">双人套餐券<span class="pt-type-tag green">优惠券</span></div>
|
||
<div class="pt-prod-price">1000积分</div>
|
||
<div class="pt-prod-meta">
|
||
<span>库存 10</span>
|
||
<span>已兑换 8</span>
|
||
</div>
|
||
<div class="pt-prod-ft">
|
||
<a class="g-action" onclick="openPtDrawer()">编辑</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>
|
||
|
||
<!-- 商品6:已下架 -->
|
||
<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">定制保温杯<span class="pt-type-tag orange">实物</span></div>
|
||
<div class="pt-prod-price">2000积分</div>
|
||
<div class="pt-prod-meta">
|
||
<span>库存 0</span>
|
||
<span>已兑换 15</span>
|
||
</div>
|
||
<div class="pt-prod-ft">
|
||
<a class="g-action" onclick="openPtDrawer()">编辑</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 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>
|
||
|
||
<!-- ==================== 添加/编辑兑换商品抽屉 ==================== -->
|
||
<div class="g-drawer-mask" id="ptDrawerMask" onclick="closePtDrawer()"></div>
|
||
<div class="g-drawer" id="ptDrawer" style="width:520px;">
|
||
<div class="g-drawer-hd">
|
||
<span class="g-drawer-title">添加兑换商品</span>
|
||
<button class="g-drawer-close" onclick="closePtDrawer()">×</button>
|
||
</div>
|
||
<div class="g-drawer-bd">
|
||
|
||
<!-- 兑换类型 -->
|
||
<div class="g-form-group">
|
||
<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>
|
||
<div class="pt-upload-placeholder">
|
||
<i data-lucide="upload-cloud" style="width:28px;height:28px;"></i>
|
||
<span>点击上传商品图片</span>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 兑换方式 -->
|
||
<div class="g-form-group">
|
||
<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>
|
||
</div>
|
||
|
||
<!-- 所需积分 -->
|
||
<div class="g-form-group">
|
||
<label class="g-form-label required">所需积分</label>
|
||
<input class="g-input" type="number" placeholder="请输入所需积分数量" min="0">
|
||
</div>
|
||
|
||
<!-- 现金部分(默认隐藏) -->
|
||
<div class="g-form-group" id="ptCashField" style="display:none;">
|
||
<label class="g-form-label required">现金部分</label>
|
||
<input class="g-input" type="number" placeholder="请输入需额外支付的金额" min="0" step="0.01">
|
||
<div class="g-hint">用户兑换时需额外支付的现金金额</div>
|
||
</div>
|
||
|
||
<!-- 库存数量 -->
|
||
<div class="g-form-group">
|
||
<label class="g-form-label required">库存数量</label>
|
||
<input class="g-input" type="number" placeholder="请输入库存数量" min="0">
|
||
</div>
|
||
|
||
<!-- 兑换限制 -->
|
||
<div class="g-form-group">
|
||
<label class="g-form-label">兑换限制</label>
|
||
<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="不限" 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>
|
||
<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>
|
||
<button class="g-btn g-btn-primary">保存</button>
|
||
</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) {
|
||
document.querySelectorAll('.pt-seg-item').forEach(function(item) { item.classList.remove('active'); });
|
||
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 开关 */
|
||
function toggleSwitch(el) {
|
||
el.classList.toggle('on');
|
||
}
|
||
|
||
/* 有效期 pill 单选 */
|
||
function selectPtExpiry(el) {
|
||
document.querySelectorAll('.pt-expiry-pills .g-pill').forEach(function(p) { p.classList.remove('checked'); });
|
||
el.classList.add('checked');
|
||
var hint = document.getElementById('ptExpiryHint');
|
||
hint.style.display = el.textContent.trim() === '按年清零' ? '' : 'none';
|
||
}
|
||
|
||
/* 兑换类型切换(商品/优惠券/实物) */
|
||
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) {
|
||
el.parentElement.querySelectorAll('.g-pill').forEach(function(p) { p.classList.remove('checked'); });
|
||
el.classList.add('checked');
|
||
document.getElementById('ptCashField').style.display = type === 'mixed' ? '' : 'none';
|
||
}
|
||
|
||
/* 抽屉开关 */
|
||
function openPtDrawer() {
|
||
document.getElementById('ptDrawerMask').classList.add('open');
|
||
document.getElementById('ptDrawer').classList.add('open');
|
||
}
|
||
function closePtDrawer() {
|
||
document.getElementById('ptDrawerMask').classList.remove('open');
|
||
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>
|