437 lines
20 KiB
HTML
437 lines
20 KiB
HTML
<!-- 消息触达页 -->
|
||
<style>
|
||
.msg-toolbar { display:flex; align-items:center; gap:10px; margin-bottom:16px; background:#fff; border-radius:10px; box-shadow:var(--g-shadow-sm); padding:12px 16px; flex-wrap:wrap; }
|
||
.msg-spacer { flex:1; }
|
||
.msg-stats { display:grid; grid-template-columns:repeat(4,1fr); gap:14px; margin-bottom:16px; }
|
||
.msg-stat-card { background:#fff; border-radius:10px; box-shadow:var(--g-shadow-sm); padding:16px 20px; transition:box-shadow var(--g-transition), transform var(--g-transition); }
|
||
.msg-stat-card:hover { box-shadow:var(--g-shadow-md); transform:translateY(-1px); }
|
||
.msg-stat-label { font-size:12px; color:var(--g-text-muted); margin-bottom:6px; }
|
||
.msg-stat-value { font-size:22px; font-weight:700; color:var(--g-text); }
|
||
.msg-stat-value .msg-stat-unit { font-size:13px; font-weight:400; color:var(--g-text-secondary); margin-left:2px; }
|
||
.msg-channel-dot { display:inline-block; width:6px; height:6px; border-radius:50%; margin-right:4px; vertical-align:middle; }
|
||
.msg-open-rate { font-size:11px; color:var(--g-text-muted); margin-top:2px; }
|
||
|
||
/* Template cards */
|
||
.msg-tpl-grid { display:grid; grid-template-columns:1fr 1fr; gap:14px; }
|
||
.msg-tpl-card { background:#fff; border-radius:10px; box-shadow:var(--g-shadow-sm); padding:18px 20px; transition:box-shadow var(--g-transition), transform var(--g-transition); display:flex; flex-direction:column; }
|
||
.msg-tpl-card:hover { box-shadow:var(--g-shadow-md); transform:translateY(-1px); }
|
||
.msg-tpl-hd { display:flex; align-items:center; gap:8px; margin-bottom:10px; }
|
||
.msg-tpl-name { font-size:14px; font-weight:600; color:var(--g-text); flex:1; }
|
||
.msg-tpl-preview { font-size:12px; color:var(--g-text-secondary); line-height:1.6; display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden; margin-bottom:12px; flex:1; }
|
||
.msg-tpl-ft { display:flex; align-items:center; justify-content:space-between; margin-top:auto; }
|
||
.msg-tpl-usage { font-size:12px; color:var(--g-text-muted); }
|
||
.msg-tpl-actions { display:flex; align-items:center; gap:10px; }
|
||
.msg-tpl-actions a { font-size:12px; color:var(--primary); cursor:pointer; text-decoration:none; transition:var(--g-transition); }
|
||
.msg-tpl-actions a:hover { text-decoration:underline; }
|
||
.msg-tpl-actions a.msg-tpl-danger { color:var(--g-danger); }
|
||
|
||
/* Drawer: tag pills for target audience */
|
||
.msg-tag-pills { display:flex; flex-wrap:wrap; gap:8px; margin-top:10px; }
|
||
.msg-reach { font-size:12px; color:var(--primary); margin-top:10px; display:flex; align-items:center; gap:4px; }
|
||
.msg-tpl-link { font-size:13px; color:var(--primary); cursor:pointer; text-decoration:none; display:inline-flex; align-items:center; gap:4px; margin-top:8px; transition:var(--g-transition); }
|
||
.msg-tpl-link:hover { text-decoration:underline; }
|
||
</style>
|
||
|
||
<div>
|
||
<!-- Tabs -->
|
||
<div class="g-seg" style="margin-bottom:16px;">
|
||
<div class="g-seg-item active" onclick="switchMsgTab(this,'list')">消息列表</div>
|
||
<div class="g-seg-item" onclick="switchMsgTab(this,'tpl')">消息模板</div>
|
||
</div>
|
||
|
||
<!-- TAB 1: 消息列表 -->
|
||
<div id="msgTabList">
|
||
<div class="msg-toolbar">
|
||
<select class="g-select" style="min-width:100px">
|
||
<option>全部状态</option>
|
||
<option>已发送</option>
|
||
<option>待发送</option>
|
||
<option>草稿</option>
|
||
</select>
|
||
<select class="g-select" style="min-width:100px">
|
||
<option>全部渠道</option>
|
||
<option>站内信</option>
|
||
<option>短信</option>
|
||
<option>微信</option>
|
||
</select>
|
||
<input class="g-input" placeholder="搜索消息标题" style="width:180px" />
|
||
<span class="msg-spacer"></span>
|
||
<button class="g-btn g-btn-primary" onclick="openMsgDrawer()"><i data-lucide="plus" style="width:14px;height:14px;vertical-align:-2px;margin-right:2px;"></i> 创建消息</button>
|
||
</div>
|
||
|
||
<!-- Stats -->
|
||
<div class="msg-stats">
|
||
<div class="msg-stat-card">
|
||
<div class="msg-stat-label">本月发送</div>
|
||
<div class="msg-stat-value">12<span class="msg-stat-unit">条</span></div>
|
||
</div>
|
||
<div class="msg-stat-card">
|
||
<div class="msg-stat-label">触达人数</div>
|
||
<div class="msg-stat-value">3,680<span class="msg-stat-unit">人</span></div>
|
||
</div>
|
||
<div class="msg-stat-card">
|
||
<div class="msg-stat-label">打开率</div>
|
||
<div class="msg-stat-value">45.2<span class="msg-stat-unit">%</span></div>
|
||
</div>
|
||
<div class="msg-stat-card">
|
||
<div class="msg-stat-label">转化率</div>
|
||
<div class="msg-stat-value">12.8<span class="msg-stat-unit">%</span></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Table -->
|
||
<div class="g-card">
|
||
<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>
|
||
<div style="font-weight:500;color:var(--g-text)">新品上线通知</div>
|
||
<div class="msg-open-rate">打开率 52.3% | 转化率 15.6%</div>
|
||
</td>
|
||
<td><span class="g-tag g-tag-blue">站内信</span></td>
|
||
<td>全部会员</td>
|
||
<td>1,280</td>
|
||
<td>2026-02-10 10:00</td>
|
||
<td><span class="g-tag g-tag-green">已发送</span></td>
|
||
<td><a class="g-action">详情</a></td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<div style="font-weight:500;color:var(--g-text)">春节优惠活动</div>
|
||
<div class="msg-open-rate">打开率 48.1% | 转化率 18.2%</div>
|
||
</td>
|
||
<td><span class="g-tag g-tag-green">短信</span></td>
|
||
<td>全部会员</td>
|
||
<td>2,400</td>
|
||
<td>2026-02-08 09:30</td>
|
||
<td><span class="g-tag g-tag-green">已发送</span></td>
|
||
<td><a class="g-action">详情</a></td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<div style="font-weight:500;color:var(--g-text)">沉睡客户召回</div>
|
||
<div class="msg-open-rate">打开率 35.7% | 转化率 8.4%</div>
|
||
</td>
|
||
<td><span class="g-tag g-tag-orange">微信模板</span></td>
|
||
<td>沉睡客户(456人)</td>
|
||
<td>456</td>
|
||
<td>2026-02-05 14:00</td>
|
||
<td><span class="g-tag g-tag-green">已发送</span></td>
|
||
<td><a class="g-action">详情</a></td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<div style="font-weight:500;color:var(--g-text)">会员日提醒</div>
|
||
</td>
|
||
<td><span class="g-tag g-tag-blue">站内信</span></td>
|
||
<td>高频客户(328人)</td>
|
||
<td>328</td>
|
||
<td>2026-02-15 08:00</td>
|
||
<td><span class="g-tag g-tag-blue">待发送</span></td>
|
||
<td><a class="g-action">详情</a><a class="g-action-danger">删除</a></td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<div style="font-weight:500;color:var(--g-text)">储值优惠推送</div>
|
||
</td>
|
||
<td><span class="g-tag g-tag-green">短信</span></td>
|
||
<td>全部会员</td>
|
||
<td>—</td>
|
||
<td>—</td>
|
||
<td><span class="g-tag g-tag-gray">草稿</span></td>
|
||
<td><a class="g-action">详情</a><a class="g-action">编辑</a><a class="g-action-danger">删除</a></td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<div style="font-weight:500;color:var(--g-text)">新客欢迎礼</div>
|
||
</td>
|
||
<td><span class="g-tag g-tag-orange">微信模板</span></td>
|
||
<td>新客(86人)</td>
|
||
<td>—</td>
|
||
<td>—</td>
|
||
<td><span class="g-tag g-tag-gray">草稿</span></td>
|
||
<td><a class="g-action">详情</a><a class="g-action">编辑</a><a class="g-action-danger">删除</a></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<div class="g-pagination" style="margin-top:16px;">
|
||
<span style="font-size:13px;color:var(--g-text-secondary);">共 6 条</span>
|
||
<button class="g-page-btn" disabled><</button>
|
||
<button class="g-page-btn active">1</button>
|
||
<button class="g-page-btn">></button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- TAB 2: 消息模板 -->
|
||
<div id="msgTabTpl" style="display:none">
|
||
<div class="msg-toolbar">
|
||
<select class="g-select" style="min-width:100px">
|
||
<option>全部分类</option>
|
||
<option>营销</option>
|
||
<option>通知</option>
|
||
<option>召回</option>
|
||
</select>
|
||
<input class="g-input" placeholder="搜索模板名称" style="width:180px" />
|
||
<span class="msg-spacer"></span>
|
||
<button class="g-btn g-btn-primary"><i data-lucide="plus" style="width:14px;height:14px;vertical-align:-2px;margin-right:2px;"></i> 新建模板</button>
|
||
</div>
|
||
|
||
<div class="msg-tpl-grid">
|
||
<!-- Template 1 -->
|
||
<div class="msg-tpl-card">
|
||
<div class="msg-tpl-hd">
|
||
<span class="msg-tpl-name">新品上线通知</span>
|
||
<span class="g-tag g-tag-blue">通知</span>
|
||
</div>
|
||
<div class="msg-tpl-preview">亲爱的{name},我们上新啦!{product}现已上线,口感升级,诚意满满,快来尝鲜吧!</div>
|
||
<div class="msg-tpl-ft">
|
||
<span class="msg-tpl-usage"><i data-lucide="bar-chart-2" style="width:12px;height:12px;vertical-align:-1px;margin-right:2px;"></i>已使用 28次</span>
|
||
<div class="msg-tpl-actions">
|
||
<button class="g-btn g-btn-sm g-btn-primary" onclick="useMsgTemplate('新品上线通知','亲爱的{name},我们上新啦!{product}现已上线,口感升级,诚意满满,快来尝鲜吧!')">使用</button>
|
||
<a>编辑</a>
|
||
<a class="msg-tpl-danger">删除</a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Template 2 -->
|
||
<div class="msg-tpl-card">
|
||
<div class="msg-tpl-hd">
|
||
<span class="msg-tpl-name">节日问候</span>
|
||
<span class="g-tag g-tag-orange">营销</span>
|
||
</div>
|
||
<div class="msg-tpl-preview">亲爱的{name},{holiday}快乐!为您准备了专属优惠,下单立享折扣,温暖过节从一顿好饭开始!</div>
|
||
<div class="msg-tpl-ft">
|
||
<span class="msg-tpl-usage"><i data-lucide="bar-chart-2" style="width:12px;height:12px;vertical-align:-1px;margin-right:2px;"></i>已使用 15次</span>
|
||
<div class="msg-tpl-actions">
|
||
<button class="g-btn g-btn-sm g-btn-primary" onclick="useMsgTemplate('节日问候','亲爱的{name},{holiday}快乐!为您准备了专属优惠,下单立享折扣,温暖过节从一顿好饭开始!')">使用</button>
|
||
<a>编辑</a>
|
||
<a class="msg-tpl-danger">删除</a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Template 3 -->
|
||
<div class="msg-tpl-card">
|
||
<div class="msg-tpl-hd">
|
||
<span class="msg-tpl-name">沉睡客户召回</span>
|
||
<span class="g-tag g-tag-red">召回</span>
|
||
</div>
|
||
<div class="msg-tpl-preview">{name},好久不见!我们很想念您,特送上一份专属回归礼券,期待与您再次相遇!</div>
|
||
<div class="msg-tpl-ft">
|
||
<span class="msg-tpl-usage"><i data-lucide="bar-chart-2" style="width:12px;height:12px;vertical-align:-1px;margin-right:2px;"></i>已使用 42次</span>
|
||
<div class="msg-tpl-actions">
|
||
<button class="g-btn g-btn-sm g-btn-primary" onclick="useMsgTemplate('沉睡客户召回','{name},好久不见!我们很想念您,特送上一份专属回归礼券,期待与您再次相遇!')">使用</button>
|
||
<a>编辑</a>
|
||
<a class="msg-tpl-danger">删除</a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Template 4 -->
|
||
<div class="msg-tpl-card">
|
||
<div class="msg-tpl-hd">
|
||
<span class="msg-tpl-name">储值优惠提醒</span>
|
||
<span class="g-tag g-tag-orange">营销</span>
|
||
</div>
|
||
<div class="msg-tpl-preview">限时充值优惠!充{amount}送{gift},多充多送,优惠截止本周日,别错过!</div>
|
||
<div class="msg-tpl-ft">
|
||
<span class="msg-tpl-usage"><i data-lucide="bar-chart-2" style="width:12px;height:12px;vertical-align:-1px;margin-right:2px;"></i>已使用 19次</span>
|
||
<div class="msg-tpl-actions">
|
||
<button class="g-btn g-btn-sm g-btn-primary" onclick="useMsgTemplate('储值优惠提醒','限时充值优惠!充{amount}送{gift},多充多送,优惠截止本周日,别错过!')">使用</button>
|
||
<a>编辑</a>
|
||
<a class="msg-tpl-danger">删除</a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Template 5 -->
|
||
<div class="msg-tpl-card">
|
||
<div class="msg-tpl-hd">
|
||
<span class="msg-tpl-name">订单完成感谢</span>
|
||
<span class="g-tag g-tag-blue">通知</span>
|
||
</div>
|
||
<div class="msg-tpl-preview">感谢您的订单!期待下次光临,如有任何问题请随时联系我们,祝您用餐愉快!</div>
|
||
<div class="msg-tpl-ft">
|
||
<span class="msg-tpl-usage"><i data-lucide="bar-chart-2" style="width:12px;height:12px;vertical-align:-1px;margin-right:2px;"></i>已使用 56次</span>
|
||
<div class="msg-tpl-actions">
|
||
<button class="g-btn g-btn-sm g-btn-primary" onclick="useMsgTemplate('订单完成感谢','感谢您的订单!期待下次光临,如有任何问题请随时联系我们,祝您用餐愉快!')">使用</button>
|
||
<a>编辑</a>
|
||
<a class="msg-tpl-danger">删除</a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Template 6 -->
|
||
<div class="msg-tpl-card">
|
||
<div class="msg-tpl-hd">
|
||
<span class="msg-tpl-name">会员升级通知</span>
|
||
<span class="g-tag g-tag-blue">通知</span>
|
||
</div>
|
||
<div class="msg-tpl-preview">恭喜{name}升级为{level}会员!解锁更多专属权益,感谢您一路以来的支持与信赖!</div>
|
||
<div class="msg-tpl-ft">
|
||
<span class="msg-tpl-usage"><i data-lucide="bar-chart-2" style="width:12px;height:12px;vertical-align:-1px;margin-right:2px;"></i>已使用 33次</span>
|
||
<div class="msg-tpl-actions">
|
||
<button class="g-btn g-btn-sm g-btn-primary" onclick="useMsgTemplate('会员升级通知','恭喜{name}升级为{level}会员!解锁更多专属权益,感谢您一路以来的支持与信赖!')">使用</button>
|
||
<a>编辑</a>
|
||
<a class="msg-tpl-danger">删除</a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Drawer mask -->
|
||
<div class="g-drawer-mask" id="msgDrawerMask" onclick="closeMsgDrawer()"></div>
|
||
|
||
<!-- Create message drawer -->
|
||
<div class="g-drawer" id="msgDrawer" style="width:560px;">
|
||
<div class="g-drawer-hd">
|
||
<span class="g-drawer-title">创建消息</span>
|
||
<button class="g-drawer-close" onclick="closeMsgDrawer()"><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="msgTitle" placeholder="如:新品上线通知" />
|
||
</div>
|
||
|
||
<!-- 推送渠道 -->
|
||
<div class="g-form-group">
|
||
<label class="g-form-label required">推送渠道</label>
|
||
<div style="display:flex;gap:8px;">
|
||
<span class="g-pill checked" onclick="selectMsgChannel(this)">站内信</span>
|
||
<span class="g-pill" onclick="selectMsgChannel(this)">短信</span>
|
||
<span class="g-pill" onclick="selectMsgChannel(this)">微信模板消息</span>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 目标人群 -->
|
||
<div class="g-form-group">
|
||
<label class="g-form-label required">目标人群</label>
|
||
<select class="g-select" id="msgTargetSelect" onchange="selectMsgTarget(this)">
|
||
<option value="all">全部会员</option>
|
||
<option value="tag">按标签筛选</option>
|
||
</select>
|
||
<div id="msgTagSection" style="display:none;">
|
||
<div class="msg-tag-pills">
|
||
<span class="g-pill" onclick="toggleMsgTagPill(this)">高频客户</span>
|
||
<span class="g-pill" onclick="toggleMsgTagPill(this)">新客</span>
|
||
<span class="g-pill" onclick="toggleMsgTagPill(this)">沉睡客户</span>
|
||
<span class="g-pill" onclick="toggleMsgTagPill(this)">流失客户</span>
|
||
<span class="g-pill" onclick="toggleMsgTagPill(this)">午餐常客</span>
|
||
<span class="g-pill" onclick="toggleMsgTagPill(this)">大额消费</span>
|
||
</div>
|
||
<div class="msg-reach" id="msgReach">
|
||
<i data-lucide="users" style="width:14px;height:14px;"></i>
|
||
<span>预计触达 456人</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 消息内容 -->
|
||
<div class="g-form-group">
|
||
<label class="g-form-label required">消息内容</label>
|
||
<textarea class="g-textarea" id="msgContent" rows="5" placeholder="支持变量:{name}姓名 {level}等级"></textarea>
|
||
<div class="g-hint">可使用变量实现个性化推送</div>
|
||
</div>
|
||
|
||
<!-- 发送时间 -->
|
||
<div class="g-form-group">
|
||
<label class="g-form-label required">发送时间</label>
|
||
<div style="display:flex;gap:8px;">
|
||
<span class="g-pill checked" onclick="selectMsgSendTime(this,'now')">立即发送</span>
|
||
<span class="g-pill" onclick="selectMsgSendTime(this,'scheduled')">定时发送</span>
|
||
</div>
|
||
<div id="msgScheduleTime" style="display:none;margin-top:10px;">
|
||
<input class="g-input" type="datetime-local" style="width:240px;" />
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 选择模板 -->
|
||
<div class="g-form-group">
|
||
<a class="msg-tpl-link" onclick="switchMsgTab(document.querySelectorAll('.g-seg-item')[1],'tpl');closeMsgDrawer();">
|
||
<i data-lucide="file-text" style="width:14px;height:14px;"></i>
|
||
从模板选择
|
||
</a>
|
||
</div>
|
||
</div>
|
||
<div class="g-drawer-ft">
|
||
<button class="g-btn" onclick="closeMsgDrawer()">存为草稿</button>
|
||
<button class="g-btn g-btn-primary" onclick="closeMsgDrawer()">发送</button>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
/* Tab switching */
|
||
function switchMsgTab(el, tab) {
|
||
document.querySelectorAll('.g-seg-item').forEach(function(s){ s.classList.remove('active'); });
|
||
el.classList.add('active');
|
||
document.getElementById('msgTabList').style.display = tab === 'list' ? '' : 'none';
|
||
document.getElementById('msgTabTpl').style.display = tab === 'tpl' ? '' : 'none';
|
||
}
|
||
|
||
/* Drawer open/close */
|
||
function openMsgDrawer() {
|
||
document.getElementById('msgDrawerMask').classList.add('open');
|
||
document.getElementById('msgDrawer').classList.add('open');
|
||
}
|
||
function closeMsgDrawer() {
|
||
document.getElementById('msgDrawerMask').classList.remove('open');
|
||
document.getElementById('msgDrawer').classList.remove('open');
|
||
}
|
||
|
||
/* Channel pill: single select */
|
||
function selectMsgChannel(el) {
|
||
var pills = el.parentElement.querySelectorAll('.g-pill');
|
||
pills.forEach(function(p){ p.classList.remove('checked'); });
|
||
el.classList.add('checked');
|
||
}
|
||
|
||
/* Target audience */
|
||
function selectMsgTarget(el) {
|
||
var section = document.getElementById('msgTagSection');
|
||
section.style.display = el.value === 'tag' ? '' : 'none';
|
||
}
|
||
|
||
/* Tag pill toggle (multi-select) */
|
||
function toggleMsgTagPill(el) {
|
||
el.classList.toggle('checked');
|
||
var count = el.parentElement.querySelectorAll('.g-pill.checked').length;
|
||
var reachMap = [0, 456, 712, 980, 1240, 1580, 1860];
|
||
var reach = reachMap[count] || 0;
|
||
document.getElementById('msgReach').querySelector('span').textContent = '预计触达 ' + reach + '人';
|
||
}
|
||
|
||
/* Send time pill: single select */
|
||
function selectMsgSendTime(el, mode) {
|
||
var pills = el.parentElement.querySelectorAll('.g-pill');
|
||
pills.forEach(function(p){ p.classList.remove('checked'); });
|
||
el.classList.add('checked');
|
||
document.getElementById('msgScheduleTime').style.display = mode === 'scheduled' ? '' : 'none';
|
||
}
|
||
|
||
/* Use template: pre-fill drawer */
|
||
function useMsgTemplate(title, content) {
|
||
openMsgDrawer();
|
||
document.getElementById('msgTitle').value = title;
|
||
document.getElementById('msgContent').value = content;
|
||
}
|
||
|
||
if (typeof lucide !== 'undefined') lucide.createIcons();
|
||
</script>
|