包含商品管理(9页)和门店管理(8页)完整原型: - 全局设计系统(Swiss Modernism + Bento Box 风格) - 商品列表/详情/分类/规格/加料/套餐/标签/时段/批量工具 - 门店列表/营业时间/配送/自提/堂食/费用/员工/资质 - 通用商品选择器弹窗、SKU矩阵、渠道按分类管理
250 lines
15 KiB
HTML
250 lines
15 KiB
HTML
<!-- 配送设置页 -->
|
||
<style>
|
||
.page-delivery { max-width:960px; }
|
||
.pd-toolbar { display:flex; align-items:center; gap:12px; margin-bottom:16px; box-shadow:var(--g-shadow-sm); border-radius:10px; padding:10px 14px; background:#fff; }
|
||
.pd-toolbar select { height:34px; padding:0 10px; border:1px solid #e5e7eb; border-radius:8px; font-size:13px; outline:none; background:#fff; transition:var(--g-transition); }
|
||
.pd-toolbar select:focus { border-color:var(--primary); box-shadow:0 0 0 3px color-mix(in srgb, var(--primary) 12%, transparent); }
|
||
|
||
/* Mode Switch */
|
||
.mode-switch { display:flex; background:#f8f9fb; border-radius:8px; padding:3px; gap:2px; width:fit-content; margin-bottom:16px; }
|
||
.mode-switch-item { padding:6px 18px; border-radius:6px; font-size:13px; cursor:pointer; color:#4b5563; transition:var(--g-transition); border:none; background:none; }
|
||
.mode-switch-item.active { background:#fff; color:var(--primary); font-weight:600; box-shadow:var(--g-shadow-sm); }
|
||
|
||
/* Map Placeholder */
|
||
.map-area { width:100%; height:320px; background:#f0f5ff; border-radius:10px; border:1px dashed #adc6ff; display:flex; flex-direction:column; align-items:center; justify-content:center; color:#597ef7; margin-bottom:16px; position:relative; overflow:hidden; }
|
||
.map-area .map-icon { font-size:48px; margin-bottom:8px; opacity:0.5; }
|
||
.map-area .map-label { font-size:13px; opacity:0.7; }
|
||
.map-area .map-overlay { position:absolute; top:0; left:0; right:0; bottom:0; }
|
||
/* Fake map grid */
|
||
.map-area .grid-line { position:absolute; background:#d6e4ff; }
|
||
.map-area .grid-h { height:1px; left:0; right:0; }
|
||
.map-area .grid-v { width:1px; top:0; bottom:0; }
|
||
.map-area .map-pin { position:absolute; top:50%; left:50%; transform:translate(-50%,-100%); font-size:24px; z-index:2; }
|
||
/* Radius circles */
|
||
.map-area .radius-circle { position:absolute; top:50%; left:50%; border-radius:50%; border:2px dashed; transform:translate(-50%,-50%); }
|
||
.map-area .rc1 { width:100px; height:100px; border-color:#22c55e; background:rgba(34,197,94,0.06); }
|
||
.map-area .rc2 { width:180px; height:180px; border-color:#f59e0b; background:rgba(245,158,11,0.04); }
|
||
.map-area .rc3 { width:260px; height:260px; border-color:#ef4444; background:rgba(239,68,68,0.03); }
|
||
.map-area .rc-label { position:absolute; font-size:10px; font-weight:600; white-space:nowrap; }
|
||
.map-area .rc1 .rc-label { bottom:-16px; left:50%; transform:translateX(-50%); color:#22c55e; }
|
||
.map-area .rc2 .rc-label { bottom:-16px; left:50%; transform:translateX(-50%); color:#f59e0b; }
|
||
.map-area .rc3 .rc-label { bottom:-16px; left:50%; transform:translateX(-50%); color:#ef4444; }
|
||
|
||
/* Zone Table */
|
||
.zone-table { width:100%; border-collapse:collapse; font-size:13px; }
|
||
.zone-table th { background:#f8f9fb; padding:10px 12px; text-align:left; font-weight:600; color:#6b7280; border-bottom:1px solid #e5e7eb; }
|
||
.zone-table td { padding:10px 12px; border-bottom:1px solid #f3f4f6; color:#1a1a2e; }
|
||
.zone-table tr:last-child td { border-bottom:none; }
|
||
.zone-table tr:hover td { background:color-mix(in srgb, var(--primary) 3%, #fff); }
|
||
.zone-color { width:12px; height:12px; border-radius:3px; display:inline-block; vertical-align:middle; margin-right:6px; }
|
||
.z-link { color:var(--primary); cursor:pointer; font-size:12px; margin-right:8px; transition:var(--g-transition); }
|
||
.z-link:hover { text-decoration:underline; }
|
||
.z-link.danger { color:#ef4444; }
|
||
|
||
/* Radius Tier Cards */
|
||
.tier-list { display:flex; flex-direction:column; gap:10px; }
|
||
.tier-card { display:grid; grid-template-columns:40px 1fr 1fr 1fr 1fr auto; gap:12px; align-items:center; padding:12px 14px; background:#f8f9fb; border-radius:10px; border:none; box-shadow:var(--g-shadow-sm); transition:var(--g-transition); }
|
||
.tier-card:hover { box-shadow:var(--g-shadow-md); }
|
||
.tier-num { width:28px; height:28px; border-radius:50%; display:flex; align-items:center; justify-content:center; font-size:12px; font-weight:600; color:#fff; }
|
||
.tier-field label { font-size:11px; color:#9ca3af; display:block; margin-bottom:3px; }
|
||
.tier-field .val { font-size:13px; font-weight:500; color:#1a1a2e; }
|
||
.tier-actions { display:flex; gap:4px; }
|
||
.tier-edit { width:28px; height:28px; display:flex; align-items:center; justify-content:center; border-radius:8px; cursor:pointer; color:#9ca3af; border:none; background:none; transition:var(--g-transition); }
|
||
.tier-edit:hover { background:#fff; color:var(--primary); }
|
||
|
||
.pd-tip { font-size:12px; color:#9ca3af; margin-top:8px; display:flex; align-items:center; gap:4px; }
|
||
</style>
|
||
|
||
<div class="page-delivery">
|
||
<div class="pd-toolbar">
|
||
<select style="width:200px;">
|
||
<option>老三家外卖(朝阳店)</option>
|
||
<option>老三家外卖(海淀店)</option>
|
||
<option>老三家外卖(望京店)</option>
|
||
<option>老三家外卖(通州店)</option>
|
||
<option>老三家外卖(丰台店)</option>
|
||
</select>
|
||
<div style="flex:1;"></div>
|
||
<button class="g-btn" onclick="openCopyStoreModal('复制配送设置到其他门店')">
|
||
<i data-lucide="copy" style="width:14px;height:14px;"></i>复制到其他门店
|
||
</button>
|
||
</div>
|
||
|
||
<!-- 配送模式 -->
|
||
<div class="g-card" style="padding:0; margin-bottom:16px;">
|
||
<div class="g-card-title" style="padding:14px 18px; margin-bottom:0; border-bottom:1px solid #f5f5f5;">配送模式</div>
|
||
<div style="padding:16px 18px;">
|
||
<div class="mode-switch">
|
||
<button class="mode-switch-item active" onclick="switchDeliveryTab('radius')">按半径配送</button>
|
||
<button class="mode-switch-item" onclick="switchDeliveryTab('polygon')">按区域配送(多边形)</button>
|
||
</div>
|
||
|
||
<!-- 地图区域 -->
|
||
<div class="map-area">
|
||
<div class="grid-line grid-h" style="top:25%;"></div>
|
||
<div class="grid-line grid-h" style="top:50%;"></div>
|
||
<div class="grid-line grid-h" style="top:75%;"></div>
|
||
<div class="grid-line grid-v" style="left:25%;"></div>
|
||
<div class="grid-line grid-v" style="left:50%;"></div>
|
||
<div class="grid-line grid-v" style="left:75%;"></div>
|
||
<div class="map-pin"><i data-lucide="map-pin" style="width:16px;height:16px"></i></div>
|
||
<!-- Radius mode circles -->
|
||
<div id="radiusOverlay">
|
||
<div class="radius-circle rc3"><span class="rc-label">5km</span></div>
|
||
<div class="radius-circle rc2"><span class="rc-label">3km</span></div>
|
||
<div class="radius-circle rc1"><span class="rc-label">1km</span></div>
|
||
</div>
|
||
<!-- Polygon mode hint (hidden by default) -->
|
||
<div id="polygonOverlay" style="display:none; text-align:center;">
|
||
<div class="map-icon"><i data-lucide="map" style="width:16px;height:16px"></i></div>
|
||
<div class="map-label">点击地图绘制配送区域多边形</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 半径配送 - 距离梯度 -->
|
||
<div class="g-card" style="padding:0; margin-bottom:16px;" id="radiusSection">
|
||
<div class="g-card-title" style="padding:14px 18px; margin-bottom:0; border-bottom:1px solid #f5f5f5;">
|
||
距离梯度
|
||
<button class="g-btn g-btn-primary g-btn-sm">
|
||
<i data-lucide="plus" style="width:13px;height:13px;"></i>添加梯度
|
||
</button>
|
||
</div>
|
||
<div style="padding:16px 18px;">
|
||
<div class="tier-list">
|
||
<div class="tier-card">
|
||
<div class="tier-num" style="background:#52c41a;">1</div>
|
||
<div class="tier-field"><label>距离范围</label><div class="val">0 ~ 1 km</div></div>
|
||
<div class="tier-field"><label>配送费</label><div class="val">¥3.00</div></div>
|
||
<div class="tier-field"><label>预计送达</label><div class="val">20 分钟</div></div>
|
||
<div class="tier-field"><label>起送金额</label><div class="val">¥15.00</div></div>
|
||
<div class="tier-actions">
|
||
<button class="tier-edit"><i data-lucide="pencil" style="width:14px;height:14px;"></i></button>
|
||
<button class="tier-edit"><i data-lucide="trash-2" style="width:14px;height:14px;color:#ff4d4f;"></i></button>
|
||
</div>
|
||
</div>
|
||
<div class="tier-card">
|
||
<div class="tier-num" style="background:#faad14;">2</div>
|
||
<div class="tier-field"><label>距离范围</label><div class="val">1 ~ 3 km</div></div>
|
||
<div class="tier-field"><label>配送费</label><div class="val">¥5.00</div></div>
|
||
<div class="tier-field"><label>预计送达</label><div class="val">35 分钟</div></div>
|
||
<div class="tier-field"><label>起送金额</label><div class="val">¥20.00</div></div>
|
||
<div class="tier-actions">
|
||
<button class="tier-edit"><i data-lucide="pencil" style="width:14px;height:14px;"></i></button>
|
||
<button class="tier-edit"><i data-lucide="trash-2" style="width:14px;height:14px;color:#ff4d4f;"></i></button>
|
||
</div>
|
||
</div>
|
||
<div class="tier-card">
|
||
<div class="tier-num" style="background:#ff4d4f;">3</div>
|
||
<div class="tier-field"><label>距离范围</label><div class="val">3 ~ 5 km</div></div>
|
||
<div class="tier-field"><label>配送费</label><div class="val">¥8.00</div></div>
|
||
<div class="tier-field"><label>预计送达</label><div class="val">50 分钟</div></div>
|
||
<div class="tier-field"><label>起送金额</label><div class="val">¥25.00</div></div>
|
||
<div class="tier-actions">
|
||
<button class="tier-edit"><i data-lucide="pencil" style="width:14px;height:14px;"></i></button>
|
||
<button class="tier-edit"><i data-lucide="trash-2" style="width:14px;height:14px;color:#ff4d4f;"></i></button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="pd-tip"><i data-lucide="info" style="width:13px;height:13px;"></i>超出最大配送半径的地址将无法下单</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 多边形配送 - 区域列表 (hidden by default) -->
|
||
<div class="g-card" style="padding:0; margin-bottom:16px; display:none;" id="polygonSection">
|
||
<div class="g-card-title" style="padding:14px 18px; margin-bottom:0; border-bottom:1px solid #f5f5f5;">
|
||
配送区域
|
||
<button class="g-btn g-btn-primary g-btn-sm">
|
||
<i data-lucide="plus" style="width:13px;height:13px;"></i>绘制新区域
|
||
</button>
|
||
</div>
|
||
<div style="padding:0;">
|
||
<table class="zone-table">
|
||
<thead><tr><th>区域名称</th><th>配送费</th><th>起送金额</th><th>预计送达</th><th>优先级</th><th style="width:100px;">操作</th></tr></thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><span class="zone-color" style="background:#52c41a;"></span>核心区域</td>
|
||
<td>¥3.00</td>
|
||
<td>¥15.00</td>
|
||
<td>20 分钟</td>
|
||
<td>1</td>
|
||
<td><a class="z-link">编辑</a><a class="z-link danger">删除</a></td>
|
||
</tr>
|
||
<tr>
|
||
<td><span class="zone-color" style="background:#1890ff;"></span>朝阳CBD</td>
|
||
<td>¥5.00</td>
|
||
<td>¥20.00</td>
|
||
<td>35 分钟</td>
|
||
<td>2</td>
|
||
<td><a class="z-link">编辑</a><a class="z-link danger">删除</a></td>
|
||
</tr>
|
||
<tr>
|
||
<td><span class="zone-color" style="background:#faad14;"></span>三里屯片区</td>
|
||
<td>¥6.00</td>
|
||
<td>¥25.00</td>
|
||
<td>40 分钟</td>
|
||
<td>3</td>
|
||
<td><a class="z-link">编辑</a><a class="z-link danger">删除</a></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 通用配送设置 -->
|
||
<div class="g-card" style="padding:0; margin-bottom:16px;">
|
||
<div class="g-card-title" style="padding:14px 18px; margin-bottom:0; border-bottom:1px solid #f5f5f5;">通用设置</div>
|
||
<div style="padding:16px 18px;">
|
||
<div style="display:grid; grid-template-columns:1fr 1fr; gap:16px 24px;">
|
||
<div>
|
||
<label style="font-size:12px; color:#666; display:block; margin-bottom:6px;">免配送费门槛</label>
|
||
<div style="display:flex; align-items:center; gap:6px;">
|
||
<input type="number" value="30" placeholder="如:50" style="width:120px; height:32px; padding:0 10px; border:1px solid #d9d9d9; border-radius:6px; font-size:13px; outline:none;" />
|
||
<span style="font-size:13px; color:#666;">元</span>
|
||
</div>
|
||
<div style="font-size:11px; color:#999; margin-top:4px;">订单满此金额免配送费,留空则不启用</div>
|
||
</div>
|
||
<div>
|
||
<label style="font-size:12px; color:#666; display:block; margin-bottom:6px;">最大配送距离</label>
|
||
<div style="display:flex; align-items:center; gap:6px;">
|
||
<input type="number" value="5" placeholder="如:5" style="width:120px; height:32px; padding:0 10px; border:1px solid #d9d9d9; border-radius:6px; font-size:13px; outline:none;" />
|
||
<span style="font-size:13px; color:#666;">公里</span>
|
||
</div>
|
||
<div style="font-size:11px; color:#999; margin-top:4px;">仅半径模式生效</div>
|
||
</div>
|
||
<div>
|
||
<label style="font-size:12px; color:#666; display:block; margin-bottom:6px;">每小时最大配送单量</label>
|
||
<div style="display:flex; align-items:center; gap:6px;">
|
||
<input type="number" value="50" placeholder="如:50" style="width:120px; height:32px; padding:0 10px; border:1px solid #d9d9d9; border-radius:6px; font-size:13px; outline:none;" />
|
||
<span style="font-size:13px; color:#666;">单</span>
|
||
</div>
|
||
<div style="font-size:11px; color:#999; margin-top:4px;">达到上限后暂停接单</div>
|
||
</div>
|
||
<div>
|
||
<label style="font-size:12px; color:#666; display:block; margin-bottom:6px;">配送时间预估加成</label>
|
||
<div style="display:flex; align-items:center; gap:6px;">
|
||
<input type="number" value="10" placeholder="如:30" style="width:120px; height:32px; padding:0 10px; border:1px solid #d9d9d9; border-radius:6px; font-size:13px; outline:none;" />
|
||
<span style="font-size:13px; color:#666;">分钟</span>
|
||
</div>
|
||
<div style="font-size:11px; color:#999; margin-top:4px;">高峰期自动增加预估时间</div>
|
||
</div>
|
||
</div>
|
||
<div style="margin-top:20px; display:flex; justify-content:flex-end; gap:8px;">
|
||
<button class="g-btn">重置</button>
|
||
<button class="g-btn g-btn-primary">保存设置</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
function switchDeliveryTab(mode) {
|
||
document.querySelectorAll('.mode-switch-item').forEach(b => b.classList.remove('active'));
|
||
event.currentTarget.classList.add('active');
|
||
document.getElementById('radiusOverlay').style.display = mode === 'radius' ? '' : 'none';
|
||
document.getElementById('polygonOverlay').style.display = mode === 'polygon' ? '' : 'none';
|
||
document.getElementById('radiusSection').style.display = mode === 'radius' ? '' : 'none';
|
||
document.getElementById('polygonSection').style.display = mode === 'polygon' ? '' : 'none';
|
||
}
|
||
</script> |