feat: init project with pages and index

This commit is contained in:
2026-02-15 22:50:30 +08:00
commit f407288701
79 changed files with 25642 additions and 0 deletions

402
pages/order-refund.html Normal file
View File

@@ -0,0 +1,402 @@
<!-- 退款售后页 -->
<style>
.orf-toolbar { display:flex; align-items:center; gap:12px; margin-bottom:16px; box-shadow:var(--g-shadow-sm); border-radius:10px; padding:12px 16px; background:#fff; flex-wrap:wrap; }
.orf-toolbar .g-select { width:200px; }
.orf-toolbar input[type="date"] { height:34px; padding:0 10px; border:1px solid #e5e7eb; border-radius:8px; font-size:13px; outline:none; background:#fff; transition:var(--g-transition); color:var(--g-text); }
.orf-toolbar input[type="date"]:focus { border-color:var(--primary); box-shadow:0 0 0 3px color-mix(in srgb, var(--primary) 12%, transparent); }
.orf-date-sep { color:var(--g-text-muted); font-size:13px; }
.orf-search { width:220px; }
/* 统计卡片 */
.orf-stats { display:grid; grid-template-columns:repeat(3,1fr); gap:16px; margin-bottom:16px; }
.orf-stat-card { background:#fff; border-radius:10px; padding:18px 20px; box-shadow:var(--g-shadow-sm); display:flex; align-items:flex-start; gap:14px; transition:box-shadow var(--g-transition); }
.orf-stat-card:hover { box-shadow:var(--g-shadow-md); }
.orf-stat-icon { width:42px; height:42px; border-radius:10px; display:flex; align-items:center; justify-content:center; flex-shrink:0; }
.orf-stat-icon.blue { background:color-mix(in srgb, var(--primary) 10%, #fff); color:var(--primary); }
.orf-stat-icon.orange { background:color-mix(in srgb, var(--g-warning) 10%, #fff); color:var(--g-warning); }
.orf-stat-icon.green { background:color-mix(in srgb, var(--g-success) 10%, #fff); color:var(--g-success); }
.orf-stat-body { flex:1; }
.orf-stat-label { font-size:12px; color:var(--g-text-muted); margin-bottom:6px; }
.orf-stat-value { font-size:22px; font-weight:700; color:var(--g-text); }
.orf-stat-trend { font-size:11px; margin-top:4px; display:flex; align-items:center; gap:3px; }
.orf-stat-trend.good { color:var(--g-success); }
.orf-stat-trend.bad { color:var(--g-danger); }
/* 表格区域 */
.orf-panel { background:#fff; border-radius:10px; box-shadow:var(--g-shadow-sm); padding:16px 18px; }
.orf-seg-wrap { margin-bottom:16px; }
.orf-table-wrap { overflow-x:auto; }
.orf-dimmed { opacity:0.55; }
/* 抽屉内信息块 */
.orf-info-section { margin-bottom:20px; }
.orf-info-title { font-size:14px; font-weight:600; color:var(--g-text); padding-left:10px; border-left:3px solid var(--primary); margin-bottom:12px; }
.orf-info-grid { display:grid; grid-template-columns:1fr 1fr; gap:8px 24px; }
.orf-info-item { display:flex; flex-direction:column; gap:2px; }
.orf-info-label { font-size:12px; color:var(--g-text-muted); }
.orf-info-value { font-size:13px; color:var(--g-text); font-weight:500; }
.orf-reason-text { font-size:13px; color:var(--g-text); line-height:1.6; margin-bottom:10px; }
.orf-photo-placeholder { width:80px; height:80px; background:#f8f9fb; border:1px dashed #e5e7eb; border-radius:8px; display:flex; align-items:center; justify-content:center; color:var(--g-text-muted); font-size:11px; text-align:center; line-height:1.3; }
.orf-product-row { display:flex; align-items:center; gap:12px; padding:10px 0; border-bottom:1px solid #f3f4f6; }
.orf-product-row:last-child { border-bottom:none; }
.orf-product-img { width:48px; height:48px; background:#f8f9fb; border-radius:8px; display:flex; align-items:center; justify-content:center; color:var(--g-text-muted); flex-shrink:0; }
.orf-product-info { flex:1; }
.orf-product-name { font-size:13px; font-weight:500; color:var(--g-text); }
.orf-product-spec { font-size:12px; color:var(--g-text-muted); margin-top:2px; }
.orf-product-price { font-size:13px; font-weight:600; color:var(--g-text); white-space:nowrap; }
/* 处理操作 */
.orf-action-pills { display:flex; gap:10px; margin-bottom:14px; }
.orf-action-pill { padding:8px 20px; border-radius:8px; font-size:13px; cursor:pointer; border:1px solid #e5e7eb; background:#fff; color:var(--g-text-secondary); transition:var(--g-transition); font-weight:500; }
.orf-action-pill:hover { border-color:var(--primary); color:var(--primary); }
.orf-action-pill.selected-approve { border-color:var(--g-success); background:color-mix(in srgb, var(--g-success) 8%, #fff); color:var(--g-success); }
.orf-action-pill.selected-reject { border-color:var(--g-danger); background:color-mix(in srgb, var(--g-danger) 8%, #fff); color:var(--g-danger); }
</style>
<!-- 顶部工具栏 -->
<div class="orf-toolbar">
<select class="g-select" style="width:200px;">
<option>老三家外卖(总店)</option>
<option>老三家外卖(朝阳店)</option>
<option>老三家外卖(海淀店)</option>
<option>老三家外卖(丰台店)</option>
<option>老三家外卖(通州店)</option>
</select>
<input type="date" value="2025-02-01" />
<span class="orf-date-sep"></span>
<input type="date" value="2025-02-12" />
<input class="g-input orf-search" placeholder="订单号/退款单号" />
<div style="flex:1;"></div>
<button class="g-btn"><i data-lucide="download" style="width:14px;height:14px;"></i> 导出</button>
</div>
<!-- 统计卡片 -->
<div class="orf-stats">
<div class="orf-stat-card">
<div class="orf-stat-icon blue"><i data-lucide="trending-down" style="width:20px;height:20px;"></i></div>
<div class="orf-stat-body">
<div class="orf-stat-label">本月退款笔数</div>
<div class="orf-stat-value">23</div>
<div class="orf-stat-trend good"><i data-lucide="arrow-down-right" style="width:12px;height:12px;"></i> 较上月减少5笔</div>
</div>
</div>
<div class="orf-stat-card">
<div class="orf-stat-icon orange"><i data-lucide="dollar-sign" style="width:20px;height:20px;"></i></div>
<div class="orf-stat-body">
<div class="orf-stat-label">本月退款金额</div>
<div class="orf-stat-value">¥1,856.00</div>
<div class="orf-stat-trend good"><i data-lucide="arrow-down-right" style="width:12px;height:12px;"></i> 较上月↓¥320</div>
</div>
</div>
<div class="orf-stat-card">
<div class="orf-stat-icon green"><i data-lucide="percent" style="width:20px;height:20px;"></i></div>
<div class="orf-stat-body">
<div class="orf-stat-label">退款率</div>
<div class="orf-stat-value">2.8%</div>
<div class="orf-stat-trend good"><i data-lucide="arrow-down-right" style="width:12px;height:12px;"></i> 较上月↓0.3%</div>
</div>
</div>
</div>
<!-- 表格面板 -->
<div class="orf-panel">
<!-- 分段控制器 -->
<div class="orf-seg-wrap">
<div class="g-seg">
<div class="g-seg-item active" onclick="switchOrfTab(this)" data-tab="pending">待处理(3)</div>
<div class="g-seg-item" onclick="switchOrfTab(this)" data-tab="processed">已处理(20)</div>
</div>
</div>
<!-- 待处理表格 -->
<div id="orfTabPending" class="orf-table-wrap">
<table class="g-table">
<thead>
<tr>
<th>退款单号</th>
<th>关联订单</th>
<th>申请时间</th>
<th>顾客</th>
<th>退款原因</th>
<th>退款金额</th>
<th style="width:80px;">操作</th>
</tr>
</thead>
<tbody>
<tr>
<td style="font-weight:500;">RF20250212001</td>
<td style="color:var(--primary);cursor:pointer;">#20250212003</td>
<td>今天 12:30</td>
<td>王**</td>
<td>商品与描述不符</td>
<td style="font-weight:600;">¥68.00</td>
<td>
<a class="g-action" onclick="openOrfDrawer('RF20250212001')">处理</a>
</td>
</tr>
<tr>
<td style="font-weight:500;">RF20250212002</td>
<td style="color:var(--primary);cursor:pointer;">#20250212005</td>
<td>今天 11:45</td>
<td>赵**</td>
<td>配送超时</td>
<td style="font-weight:600;">¥35.00</td>
<td>
<a class="g-action" onclick="openOrfDrawer('RF20250212002')">处理</a>
</td>
</tr>
<tr>
<td style="font-weight:500;">RF20250212003</td>
<td style="color:var(--primary);cursor:pointer;">#20250212008</td>
<td>今天 10:20</td>
<td>孙**</td>
<td>少送商品</td>
<td style="font-weight:600;">¥15.00</td>
<td>
<a class="g-action" onclick="openOrfDrawer('RF20250212003')">处理</a>
</td>
</tr>
</tbody>
</table>
<div class="g-pagination">
<span style="font-size:13px;color:var(--g-text-secondary);margin-right:12px;">共 3 条</span>
<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" disabled><i data-lucide="chevron-right" style="width:14px;height:14px;"></i></button>
</div>
</div>
<!-- 已处理表格 -->
<div id="orfTabProcessed" class="orf-table-wrap" style="display:none;">
<table class="g-table">
<thead>
<tr>
<th>退款单号</th>
<th>关联订单</th>
<th>申请时间</th>
<th>顾客</th>
<th>退款原因</th>
<th>退款金额</th>
<th>处理结果</th>
<th>处理时间</th>
<th style="width:60px;">操作</th>
</tr>
</thead>
<tbody>
<tr>
<td style="font-weight:500;">RF20250211012</td>
<td style="color:var(--primary);cursor:pointer;">#20250211018</td>
<td>昨天 14:20</td>
<td>李**</td>
<td>商品质量问题</td>
<td style="font-weight:600;">¥42.00</td>
<td><span class="g-tag g-tag-green">已退款</span></td>
<td>昨天 15:05</td>
<td><a class="g-action" onclick="openOrfDrawer('RF20250211012')">详情</a></td>
<tr>
<td style="font-weight:500;">RF20250211008</td>
<td style="color:var(--primary);cursor:pointer;">#20250211010</td>
<td>昨天 11:30</td>
<td>张**</td>
<td>配送超时</td>
<td style="font-weight:600;">¥28.50</td>
<td><span class="g-tag g-tag-green">已退款</span></td>
<td>昨天 12:10</td>
<td><a class="g-action" onclick="openOrfDrawer('RF20250211008')">详情</a></td>
<tr class="orf-dimmed">
<td style="font-weight:500;">RF20250210015</td>
<td style="color:var(--primary);cursor:pointer;">#20250210022</td>
<td>02-10 16:45</td>
<td>周**</td>
<td>不想要了</td>
<td style="font-weight:600;">¥56.00</td>
<td><span class="g-tag g-tag-red">已拒绝</span></td>
<td>02-10 17:20</td>
<td><a class="g-action" onclick="openOrfDrawer('RF20250210015')">详情</a></td>
<tr>
<td style="font-weight:500;">RF20250210009</td>
<td style="color:var(--primary);cursor:pointer;">#20250210014</td>
<td>02-10 12:00</td>
<td>吴**</td>
<td>少送商品</td>
<td style="font-weight:600;">¥18.00</td>
<td><span class="g-tag g-tag-green">已退款</span></td>
<td>02-10 13:30</td>
<td><a class="g-action" onclick="openOrfDrawer('RF20250210009')">详情</a></td>
<tr class="orf-dimmed">
<td style="font-weight:500;">RF20250209021</td>
<td style="color:var(--primary);cursor:pointer;">#20250209030</td>
<td>02-09 19:10</td>
<td>陈**</td>
<td>商品与描述不符</td>
<td style="font-weight:600;">¥75.00</td>
<td><span class="g-tag g-tag-red">已拒绝</span></td>
<td>02-09 20:00</td>
<td><a class="g-action" onclick="openOrfDrawer('RF20250209021')">详情</a></td>
</tbody>
</table>
<div class="g-pagination">
<span style="font-size:13px;color:var(--g-text-secondary);margin-right:12px;">共 20 条</span>
<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">4</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="orfDrawerMask" onclick="closeOrfDrawer()"></div>
<div class="g-drawer" id="orfDrawer" style="width:480px;">
<div class="g-drawer-hd">
<span class="g-drawer-title">退款处理</span>
<span class="g-drawer-close" onclick="closeOrfDrawer()"><i data-lucide="x" style="width:18px;height:18px;"></i></span>
</div>
<div class="g-drawer-bd">
<!-- 退款信息 -->
<div class="orf-info-section">
<div class="orf-info-title">退款信息</div>
<div class="orf-info-grid">
<div class="orf-info-item">
<span class="orf-info-label">退款单号</span>
<span class="orf-info-value" id="orfDetailNo">RF20250212001</span>
</div>
<div class="orf-info-item">
<span class="orf-info-label">关联订单</span>
<span class="orf-info-value" style="color:var(--primary);cursor:pointer;" id="orfDetailOrder">#20250212003</span>
</div>
<div class="orf-info-item">
<span class="orf-info-label">申请时间</span>
<span class="orf-info-value" id="orfDetailTime">今天 12:30</span>
</div>
<div class="orf-info-item">
<span class="orf-info-label">顾客</span>
<span class="orf-info-value" id="orfDetailCustomer">王**</span>
</div>
<div class="orf-info-item">
<span class="orf-info-label">退款金额</span>
<span class="orf-info-value" style="color:var(--g-danger);font-size:16px;" id="orfDetailAmount">¥68.00</span>
</div>
</div>
</div>
<!-- 退款原因 -->
<div class="orf-info-section">
<div class="orf-info-title">退款原因</div>
<div class="orf-reason-text" id="orfDetailReason">商品与描述不符,收到的菜品和图片差距较大,口味也不对。</div>
<div class="orf-photo-placeholder"><i data-lucide="image" style="width:20px;height:20px;margin-bottom:2px;"></i><br/>顾客上传图片</div>
</div>
<!-- 商品信息 -->
<div class="orf-info-section">
<div class="orf-info-title">商品信息</div>
<div class="orf-product-row">
<div class="orf-product-img"><i data-lucide="utensils" style="width:20px;height:20px;"></i></div>
<div class="orf-product-info">
<div class="orf-product-name">香辣鸡腿堡套餐</div>
<div class="orf-product-spec">大份 / 微辣 x1</div>
</div>
<div class="orf-product-price">¥38.00</div>
</div>
<div class="orf-product-row">
<div class="orf-product-img"><i data-lucide="cup-soda" style="width:20px;height:20px;"></i></div>
<div class="orf-product-info">
<div class="orf-product-name">冰红茶(大杯)</div>
<div class="orf-product-spec">加冰 x1</div>
</div>
<div class="orf-product-price">¥12.00</div>
</div>
<div class="orf-product-row">
<div class="orf-product-img"><i data-lucide="cookie" style="width:20px;height:20px;"></i></div>
<div class="orf-product-info">
<div class="orf-product-name">蛋挞2只装</div>
<div class="orf-product-spec">x1</div>
</div>
<div class="orf-product-price">¥18.00</div>
</div>
</div>
<!-- 处理操作 -->
<div class="orf-info-section">
<div class="orf-info-title">处理操作</div>
<div class="orf-action-pills">
<div class="orf-action-pill" onclick="selectOrfAction(this, 'approve')"><i data-lucide="check" style="width:14px;height:14px;vertical-align:-2px;margin-right:4px;"></i>同意退款</div>
<div class="orf-action-pill" onclick="selectOrfAction(this, 'reject')"><i data-lucide="x" style="width:14px;height:14px;vertical-align:-2px;margin-right:4px;"></i>拒绝退款</div>
</div>
<div id="orfRejectArea" style="display:none;">
<div class="g-form-group">
<label class="g-form-label required">拒绝原因</label>
<textarea class="g-textarea" rows="3" placeholder="请输入拒绝原因,如:商品已确认送达"></textarea>
<div class="g-hint">拒绝原因将通知顾客,请认真填写</div>
</div>
</div>
</div>
</div>
<div class="g-drawer-ft">
<button class="g-btn" onclick="closeOrfDrawer()">取消</button>
<button class="g-btn g-btn-primary">提交</button>
</div>
</div>
<script>
/* 切换待处理/已处理 tab */
function switchOrfTab(el) {
var tab = el.getAttribute('data-tab');
el.parentElement.querySelectorAll('.g-seg-item').forEach(function(item) {
item.classList.remove('active');
});
el.classList.add('active');
document.getElementById('orfTabPending').style.display = tab === 'pending' ? '' : 'none';
document.getElementById('orfTabProcessed').style.display = tab === 'processed' ? '' : 'none';
}
/* 退款详情数据映射(原型模拟) */
var orfMockData = {
'RF20250212001': { no:'RF20250212001', order:'#20250212003', time:'今天 12:30', customer:'王**', amount:'¥68.00', reason:'商品与描述不符,收到的菜品和图片差距较大,口味也不对。' },
'RF20250212002': { no:'RF20250212002', order:'#20250212005', time:'今天 11:45', customer:'赵**', amount:'¥35.00', reason:'配送超时,等了将近一个小时才送到,食物已经凉了。' },
'RF20250212003': { no:'RF20250212003', order:'#20250212008', time:'今天 10:20', customer:'孙**', amount:'¥15.00', reason:'少送了一份蛋挞,订单里有但是没收到。' }
};
/* 打开抽屉 */
function openOrfDrawer(refundNo) {
var data = orfMockData[refundNo];
if (data) {
document.getElementById('orfDetailNo').textContent = data.no;
document.getElementById('orfDetailOrder').textContent = data.order;
document.getElementById('orfDetailTime').textContent = data.time;
document.getElementById('orfDetailCustomer').textContent = data.customer;
document.getElementById('orfDetailAmount').textContent = data.amount;
document.getElementById('orfDetailReason').textContent = data.reason;
}
/* 重置操作状态 */
document.querySelectorAll('.orf-action-pill').forEach(function(p) {
p.classList.remove('selected-approve', 'selected-reject');
});
document.getElementById('orfRejectArea').style.display = 'none';
document.getElementById('orfDrawerMask').classList.add('open');
document.getElementById('orfDrawer').classList.add('open');
}
/* 关闭抽屉 */
function closeOrfDrawer() {
document.getElementById('orfDrawerMask').classList.remove('open');
document.getElementById('orfDrawer').classList.remove('open');
}
/* 选择同意/拒绝 */
function selectOrfAction(el, action) {
document.querySelectorAll('.orf-action-pill').forEach(function(p) {
p.classList.remove('selected-approve', 'selected-reject');
});
if (action === 'approve') {
el.classList.add('selected-approve');
document.getElementById('orfRejectArea').style.display = 'none';
} else {
el.classList.add('selected-reject');
document.getElementById('orfRejectArea').style.display = '';
}
}
</script>