feat: 管理端场所/分类管理增强及小程序端交互优化
- 后台营养管理:场所新增/编辑页重构(营业时段/图片/资质)、食材及餐品分类管理弹窗、从已有食材复制 - 营养管理小程序:净菜包订单按状态差异化展示、时间选择器交互重构、新增收货地址页、移除营养目标分区 - CHANGELOG 更新至 2026-07-23 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
bab86f72f3
commit
ea8239debf
@@ -92,16 +92,42 @@
|
||||
.pickup-method .pm-name { font-size: 13px; font-weight: 600; margin-top: 4px; color: #333; }
|
||||
.pickup-method .pm-desc { font-size: 10px; color: #999; margin-top: 2px; }
|
||||
.pickup-method.active .pm-name { color: #1677ff; }
|
||||
/* 日期/时段 chip */
|
||||
.chip-label { font-size: 11px; color: #999; margin: 8px 0 6px; }
|
||||
.date-chips, .time-chips { display: flex; gap: 6px; flex-wrap: wrap; }
|
||||
.date-chip, .time-chip {
|
||||
padding: 6px 10px; border-radius: 14px; background: #f5f5f5;
|
||||
font-size: 11px; color: #666; cursor: pointer; line-height: 1.4;
|
||||
/* 期望配送时间:下拉框风格 */
|
||||
.time-picker-trigger {
|
||||
display: flex; align-items: center; justify-content: space-between;
|
||||
height: 38px; padding: 0 12px; border-radius: 8px;
|
||||
border: 1px solid #e8e8e8; background: #fff; cursor: pointer;
|
||||
}
|
||||
.date-chip.active, .time-chip.active {
|
||||
background: #1677ff; color: #fff; font-weight: 600;
|
||||
.tpt-text { font-size: 13px; color: #333; }
|
||||
.tpt-arrow { font-size: 10px; color: #999; transition: transform 0.2s; }
|
||||
.tpt-arrow.open { transform: rotate(180deg); }
|
||||
.time-picker-panel {
|
||||
display: none; margin-top: 6px; gap: 8px;
|
||||
}
|
||||
.time-picker-panel.show { display: flex; }
|
||||
.tp-date-col {
|
||||
width: 88px; flex-shrink: 0; display: flex; flex-direction: column; gap: 4px;
|
||||
}
|
||||
.tp-date-card {
|
||||
padding: 7px 6px; border-radius: 6px; border: 1px solid #e8e8e8;
|
||||
text-align: center; cursor: pointer; background: #fff; transition: all 0.15s;
|
||||
}
|
||||
.tp-date-card.active { border-color: #1677ff; background: #e6f4ff; }
|
||||
.tp-date-card .tp-date-week { font-size: 10px; color: #999; margin-bottom: 2px; }
|
||||
.tp-date-card.active .tp-date-week { color: #1677ff; font-weight: 600; }
|
||||
.tp-date-card .tp-date-day { font-size: 12px; color: #333; font-weight: 600; }
|
||||
.tp-date-card.active .tp-date-day { color: #1677ff; }
|
||||
.tp-time-col {
|
||||
flex: 1; max-height: 220px; overflow-y: auto;
|
||||
display: flex; flex-direction: column; gap: 2px;
|
||||
border: 1px solid #e8e8e8; border-radius: 6px; padding: 4px 6px;
|
||||
}
|
||||
.tp-time-col::-webkit-scrollbar { display: none; }
|
||||
.tp-time-item {
|
||||
padding: 6px 10px; border-radius: 6px; font-size: 12px; color: #333;
|
||||
cursor: pointer; text-align: center; transition: all 0.15s;
|
||||
}
|
||||
.tp-time-item.active { background: #1677ff; color: #fff; font-weight: 600; }
|
||||
/* 地址卡片 */
|
||||
.address-card, .pickup-card {
|
||||
padding: 12px; border-radius: 8px; border: 1px solid #e8e8e8; background: #fafafa;
|
||||
@@ -225,8 +251,6 @@
|
||||
</div>
|
||||
<!-- 净菜包订单:履约信息表单(预售,必填取货方式 + 期望时间) -->
|
||||
<div class="fulfill-card hidden" id="fulfillBlock">
|
||||
<div class="fulfill-title">📦 履约信息</div>
|
||||
<div class="presale-tip">⏰ 净菜包为<b>预售商品</b>,当日 <b>15:00 截单</b>,次日按所选时段配送/自提。</div>
|
||||
<!-- 取货方式 -->
|
||||
<div class="form-group">
|
||||
<div class="fg-label">取货方式 <span class="required">*</span></div>
|
||||
@@ -243,20 +267,43 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 期望配送时间 -->
|
||||
<!-- 期望配送时间:下拉框风格,左日期右时段 -->
|
||||
<div class="form-group">
|
||||
<div class="fg-label">期望配送时间 <span class="required">*</span></div>
|
||||
<div class="chip-label">选择日期</div>
|
||||
<div class="date-chips">
|
||||
<div class="date-chip">今日(4月28日)</div>
|
||||
<div class="date-chip active">明日(4月29日)</div>
|
||||
<div class="date-chip">4月30日</div>
|
||||
<div class="time-picker-trigger" id="timePickerTrigger">
|
||||
<span class="tpt-text" id="tptText">4月30日 周五 | 11:00-12:00</span>
|
||||
<span class="tpt-arrow" id="tptArrow">▼</span>
|
||||
</div>
|
||||
<div class="chip-label">选择时段</div>
|
||||
<div class="time-chips">
|
||||
<div class="time-chip">早餐 07:00-08:00</div>
|
||||
<div class="time-chip active">午餐 11:00-12:00</div>
|
||||
<div class="time-chip">晚餐 17:00-18:00</div>
|
||||
<div class="time-picker-panel" id="timePickerPanel">
|
||||
<div class="tp-date-col">
|
||||
<div class="tp-date-card active" data-week="周五" data-day="4月30日">
|
||||
<div class="tp-date-week">周五</div>
|
||||
<div class="tp-date-day">4月30日</div>
|
||||
</div>
|
||||
<div class="tp-date-card" data-week="周六" data-day="5月1日">
|
||||
<div class="tp-date-week">周六</div>
|
||||
<div class="tp-date-day">5月1日</div>
|
||||
</div>
|
||||
<div class="tp-date-card" data-week="周日" data-day="5月2日">
|
||||
<div class="tp-date-week">周日</div>
|
||||
<div class="tp-date-day">5月2日</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tp-time-col">
|
||||
<div class="tp-time-item">07:00-08:00</div>
|
||||
<div class="tp-time-item">08:00-09:00</div>
|
||||
<div class="tp-time-item">09:00-10:00</div>
|
||||
<div class="tp-time-item">10:00-11:00</div>
|
||||
<div class="tp-time-item active">11:00-12:00</div>
|
||||
<div class="tp-time-item">12:00-13:00</div>
|
||||
<div class="tp-time-item">13:00-14:00</div>
|
||||
<div class="tp-time-item">14:00-15:00</div>
|
||||
<div class="tp-time-item">15:00-16:00</div>
|
||||
<div class="tp-time-item">16:00-17:00</div>
|
||||
<div class="tp-time-item">17:00-18:00</div>
|
||||
<div class="tp-time-item">18:00-19:00</div>
|
||||
<div class="tp-time-item">19:00-20:00</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 配送地址(仅 delivery,支持选择/新增) -->
|
||||
@@ -371,7 +418,8 @@
|
||||
var orderAmount = document.getElementById('orderAmount');
|
||||
var actionBtns = document.getElementById('actionBtns');
|
||||
|
||||
/* 取货方式切换:联动地址组/自提组显示 */
|
||||
/* 取货方式切换:联动地址组/自提组 + 时间标签文本 */
|
||||
var timeLabel = document.querySelectorAll('.fulfill-card .fg-label')[1];
|
||||
document.querySelectorAll('.pickup-method').forEach(function(m) {
|
||||
m.addEventListener('click', function() {
|
||||
document.querySelectorAll('.pickup-method').forEach(function(x) { x.classList.remove('active'); });
|
||||
@@ -379,22 +427,63 @@
|
||||
var isDelivery = m.dataset.method === 'delivery';
|
||||
document.getElementById('addressGroup').classList.toggle('hidden', !isDelivery);
|
||||
document.getElementById('pickupGroup').classList.toggle('hidden', isDelivery);
|
||||
/* 切换标签文本 */
|
||||
if (isDelivery) {
|
||||
timeLabel.innerHTML = '期望配送时间 <span class="required">*</span>';
|
||||
} else {
|
||||
timeLabel.innerHTML = '自提时间 <span class="required">*</span>';
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
/* 日期 chip 单选切换 */
|
||||
document.querySelectorAll('.date-chip').forEach(function(c) {
|
||||
c.addEventListener('click', function() {
|
||||
document.querySelectorAll('.date-chip').forEach(function(x) { x.classList.remove('active'); });
|
||||
/* 下拉面板展开/收起 */
|
||||
var timePickerTrigger = document.getElementById('timePickerTrigger');
|
||||
var timePickerPanel = document.getElementById('timePickerPanel');
|
||||
var tptText = document.getElementById('tptText');
|
||||
var tptArrow = document.getElementById('tptArrow');
|
||||
|
||||
timePickerTrigger.addEventListener('click', function(e) {
|
||||
e.stopPropagation();
|
||||
var isOpen = timePickerPanel.classList.toggle('show');
|
||||
if (isOpen) { tptArrow.classList.add('open'); }
|
||||
else { tptArrow.classList.remove('open'); }
|
||||
});
|
||||
|
||||
/* 点击面板外部关闭 */
|
||||
document.addEventListener('click', function(e) {
|
||||
if (!timePickerTrigger.contains(e.target) && !timePickerPanel.contains(e.target)) {
|
||||
timePickerPanel.classList.remove('show');
|
||||
tptArrow.classList.remove('open');
|
||||
}
|
||||
});
|
||||
|
||||
/* 更新触发区显示文本 */
|
||||
function updateTriggerText() {
|
||||
var activeDate = document.querySelector('.tp-date-card.active');
|
||||
var activeTime = document.querySelector('.tp-time-item.active');
|
||||
var week = activeDate ? activeDate.dataset.week : '';
|
||||
var day = activeDate ? activeDate.dataset.day : '';
|
||||
var time = activeTime ? activeTime.textContent : '';
|
||||
tptText.textContent = day + ' ' + week + ' | ' + time;
|
||||
}
|
||||
|
||||
/* 日期卡片单选切换 */
|
||||
document.querySelectorAll('.tp-date-card').forEach(function(c) {
|
||||
c.addEventListener('click', function(e) {
|
||||
e.stopPropagation();
|
||||
document.querySelectorAll('.tp-date-card').forEach(function(x) { x.classList.remove('active'); });
|
||||
c.classList.add('active');
|
||||
updateTriggerText();
|
||||
});
|
||||
});
|
||||
|
||||
/* 时段 chip 单选切换 */
|
||||
document.querySelectorAll('.time-chip').forEach(function(c) {
|
||||
c.addEventListener('click', function() {
|
||||
document.querySelectorAll('.time-chip').forEach(function(x) { x.classList.remove('active'); });
|
||||
/* 时段列表项单选切换 */
|
||||
document.querySelectorAll('.tp-time-item').forEach(function(c) {
|
||||
c.addEventListener('click', function(e) {
|
||||
e.stopPropagation();
|
||||
document.querySelectorAll('.tp-time-item').forEach(function(x) { x.classList.remove('active'); });
|
||||
c.classList.add('active');
|
||||
updateTriggerText();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -473,7 +562,7 @@
|
||||
/* 净菜包订单:改为"确认订单"页,隐藏取餐码,展示履约表单 */
|
||||
successIcon.textContent = '📝';
|
||||
successTitle.textContent = '确认订单信息';
|
||||
successDesc.textContent = '请补充履约信息后提交订单';
|
||||
successDesc.textContent = '请先选择配送方式后再提交订单';
|
||||
pickupBlock.classList.add('hidden');
|
||||
fulfillBlock.classList.remove('hidden');
|
||||
orderItems.innerHTML =
|
||||
|
||||
@@ -68,9 +68,15 @@
|
||||
.menu-item .food-icon {
|
||||
width: 56px; height: 56px; border-radius: 10px; background: #f5f5f5;
|
||||
display: flex; align-items: center; justify-content: center; font-size: 28px; flex-shrink: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
.menu-item .food-info { flex: 1; min-width: 0; }
|
||||
.menu-item .food-name { font-size: 14px; font-weight: 600; display: flex; align-items: center; gap: 4px; flex-wrap: wrap; }
|
||||
.menu-item .food-name {
|
||||
font-size: 14px; font-weight: 600; display: flex; align-items: center; gap: 4px; flex-wrap: wrap;
|
||||
cursor: pointer;
|
||||
}
|
||||
.menu-item .food-name:hover { color: #1677ff; }
|
||||
.menu-item .food-desc { cursor: pointer; }
|
||||
.food-tag {
|
||||
font-size: 10px; font-weight: 600; padding: 1px 5px; border-radius: 3px;
|
||||
white-space: nowrap; line-height: 16px;
|
||||
@@ -236,7 +242,7 @@
|
||||
<div class="menu-item" data-price="22">
|
||||
<div class="food-icon">🍗</div>
|
||||
<div class="food-info">
|
||||
<div class="food-name">宫保鸡丁净菜包</div>
|
||||
<div class="food-name">宫保鸡丁</div>
|
||||
<div class="food-desc">腌好鸡丁+配料包 · 约300g · 285kcal</div>
|
||||
<div class="food-bottom">
|
||||
<span class="food-price">¥22</span>
|
||||
@@ -248,7 +254,7 @@
|
||||
<div class="menu-item" data-price="10">
|
||||
<div class="food-icon">🍅</div>
|
||||
<div class="food-info">
|
||||
<div class="food-name">番茄炒蛋净菜包</div>
|
||||
<div class="food-name">番茄炒蛋</div>
|
||||
<div class="food-desc">切好番茄+调好蛋液 · 约250g · 168kcal</div>
|
||||
<div class="food-bottom">
|
||||
<span class="food-price">¥10</span>
|
||||
@@ -260,7 +266,7 @@
|
||||
<div class="menu-item" data-price="26">
|
||||
<div class="food-icon">🍖</div>
|
||||
<div class="food-info">
|
||||
<div class="food-name">红烧肉净菜包</div>
|
||||
<div class="food-name">红烧肉</div>
|
||||
<div class="food-desc">炖好五花肉+酱料包 · 约350g · 395kcal</div>
|
||||
<div class="food-bottom">
|
||||
<span class="food-price">¥26</span>
|
||||
@@ -272,7 +278,7 @@
|
||||
<div class="menu-item" data-price="28">
|
||||
<div class="food-icon">🐟</div>
|
||||
<div class="food-info">
|
||||
<div class="food-name">清蒸鱼净菜包</div>
|
||||
<div class="food-name">清蒸鱼</div>
|
||||
<div class="food-desc">处理净草鱼+葱姜丝 · 约220g · 142kcal</div>
|
||||
<div class="food-bottom">
|
||||
<span class="food-price">¥28</span>
|
||||
@@ -284,7 +290,7 @@
|
||||
<div class="menu-item" data-price="35">
|
||||
<div class="food-icon">🥗</div>
|
||||
<div class="food-info">
|
||||
<div class="food-name">低脂控糖套餐净菜包</div>
|
||||
<div class="food-name">低脂控糖套餐</div>
|
||||
<div class="food-desc">鸡胸+糙米饭+西兰花 · 约400g · 320kcal</div>
|
||||
<div class="food-bottom">
|
||||
<span class="food-price">¥35</span>
|
||||
@@ -296,7 +302,7 @@
|
||||
<div class="menu-item" data-price="68">
|
||||
<div class="food-icon">🍱</div>
|
||||
<div class="food-info">
|
||||
<div class="food-name">2-3人家庭套餐净菜包</div>
|
||||
<div class="food-name">2-3人家庭套餐</div>
|
||||
<div class="food-desc">3菜1汤半成品 · 约1.2kg · 1200kcal</div>
|
||||
<div class="food-bottom">
|
||||
<span class="food-price">¥68</span>
|
||||
@@ -420,6 +426,27 @@
|
||||
|
||||
/* 初始化:购物车归零 */
|
||||
updateCart();
|
||||
|
||||
/* 菜品点击查看详情:餐品和净菜包统一跳转 eat-dish-detail.html */
|
||||
var detailTarget = { 'panel-meal': 'eat-dish-detail.html', 'panel-clean': 'eat-dish-detail.html' };
|
||||
|
||||
document.querySelectorAll('.menu-item').forEach(function(item) {
|
||||
/* 根据 menu-item 所在面板解析目标页 */
|
||||
var panel = item.closest('.order-layout');
|
||||
var target = panel && detailTarget[panel.id] ? detailTarget[panel.id] : 'eat-dish-detail.html';
|
||||
var triggerHandler = function(e) {
|
||||
/* 避免点到加减按钮区域 */
|
||||
if (e.target.closest('.food-bottom')) return;
|
||||
location.href = target;
|
||||
};
|
||||
/* 图标、名称、描述可点击跳转,加减按钮不受影响 */
|
||||
var icon = item.querySelector('.food-icon');
|
||||
var name = item.querySelector('.food-name');
|
||||
var desc = item.querySelector('.food-desc');
|
||||
[icon, name, desc].forEach(function(el) {
|
||||
if (el) el.addEventListener('click', triggerHandler);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -0,0 +1,426 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>收货地址 | 智能餐养小程序</title>
|
||||
<style>
|
||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
body {
|
||||
background: #2a2a2a; display: flex; justify-content: center; align-items: flex-start;
|
||||
min-height: 100vh; font-family: -apple-system, BlinkMacSystemFont, 'PingFang SC', 'Helvetica Neue', sans-serif;
|
||||
padding: 24px 0 40px;
|
||||
}
|
||||
.phone-shell {
|
||||
width: 390px; height: 844px; background: #fff; border-radius: 44px;
|
||||
box-shadow: 0 20px 60px rgba(0,0,0,0.3), inset 0 0 0 2px #e0e0e0;
|
||||
overflow: hidden; position: relative; display: flex; flex-direction: column;
|
||||
}
|
||||
.status-bar {
|
||||
height: 44px; background: #fff; display: flex; align-items: center;
|
||||
justify-content: space-between; padding: 0 24px; font-size: 12px; font-weight: 600; flex-shrink: 0;
|
||||
}
|
||||
.status-bar .time { font-size: 15px; font-weight: 700; }
|
||||
.status-bar .icons { display: flex; gap: 6px; align-items: center; }
|
||||
.nav-bar { height: 44px; background: #fff; display: flex; align-items: center; padding: 0 16px; border-bottom: 0.5px solid #f0f0f0; flex-shrink: 0; position: relative; }
|
||||
.nav-bar .back { font-size: 22px; color: #1677ff; cursor: pointer; text-decoration: none; line-height: 1; }
|
||||
.nav-bar .title { position: absolute; left: 50%; transform: translateX(-50%); font-size: 17px; font-weight: 600; }
|
||||
.home-indicator {
|
||||
height: 20px; display: flex; align-items: center; justify-content: center; background: #fff; flex-shrink: 0;
|
||||
}
|
||||
.home-indicator::after { content: ''; width: 120px; height: 5px; background: #1a1a1a; border-radius: 3px; opacity: 0.2; }
|
||||
.page-content { flex: 1; overflow-y: auto; background: #f5f5f5; padding-bottom: 16px; }
|
||||
.page-content::-webkit-scrollbar { display: none; }
|
||||
|
||||
/* 地址卡片 */
|
||||
.addr-card {
|
||||
margin: 12px 16px 0; background: #fff; border-radius: 12px; padding: 14px;
|
||||
position: relative; box-shadow: 0 1px 4px rgba(0,0,0,0.04);
|
||||
}
|
||||
.addr-card .ac-top { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; flex-wrap: wrap; }
|
||||
.addr-card .ac-name { font-size: 15px; font-weight: 600; color: #333; }
|
||||
.addr-card .ac-phone { font-size: 13px; color: #666; }
|
||||
.addr-card .ac-default {
|
||||
font-size: 10px; padding: 1px 6px; border-radius: 8px; background: #fff7e6; color: #fa8c16; font-weight: 600;
|
||||
}
|
||||
.addr-card .ac-detail { font-size: 13px; color: #555; line-height: 1.6; padding-right: 70px; }
|
||||
.addr-card .ac-actions {
|
||||
position: absolute; right: 12px; bottom: 12px; display: flex; gap: 6px;
|
||||
}
|
||||
.addr-card .ac-btn {
|
||||
font-size: 12px; padding: 3px 10px; border-radius: 12px; border: none; cursor: pointer;
|
||||
background: #f5f5f5; color: #666;
|
||||
}
|
||||
.addr-card .ac-btn.primary { background: #e6f4ff; color: #1677ff; }
|
||||
|
||||
/* 编辑表单 */
|
||||
.addr-form {
|
||||
margin: 10px 0 0; padding: 12px; border-radius: 8px; background: #fafafa; border: 1px solid #e8e8e8;
|
||||
display: none;
|
||||
}
|
||||
.addr-form.show { display: block; }
|
||||
.addr-form .form-row { padding: 8px 0; border-bottom: 0.5px solid #f0f0f0; }
|
||||
.addr-form .form-row:last-of-type { border-bottom: none; }
|
||||
.addr-form .form-label { font-size: 12px; color: #666; margin-bottom: 6px; }
|
||||
.addr-form .form-label .required { color: #f5222d; }
|
||||
.addr-form .form-input {
|
||||
width: 100%; height: 34px; border-radius: 6px; border: 1px solid #e8e8e8;
|
||||
padding: 0 10px; font-size: 13px; background: #fff; outline: none;
|
||||
}
|
||||
.addr-form .form-input:focus { border-color: #1677ff; }
|
||||
.addr-form .form-textarea {
|
||||
width: 100%; min-height: 56px; border-radius: 6px; border: 1px solid #e8e8e8;
|
||||
padding: 8px 10px; font-size: 13px; background: #fff; outline: none; resize: none; font-family: inherit;
|
||||
}
|
||||
.addr-form .form-textarea:focus { border-color: #1677ff; }
|
||||
.addr-form .form-switch {
|
||||
display: flex; align-items: center; justify-content: space-between; font-size: 13px; color: #333;
|
||||
}
|
||||
.switch-toggle {
|
||||
width: 36px; height: 20px; border-radius: 10px; background: #d9d9d9; position: relative;
|
||||
cursor: pointer; transition: background 0.2s; border: none;
|
||||
}
|
||||
.switch-toggle::after {
|
||||
content: ''; position: absolute; left: 2px; top: 2px; width: 16px; height: 16px;
|
||||
border-radius: 50%; background: #fff; transition: left 0.2s;
|
||||
}
|
||||
.switch-toggle.on { background: #1677ff; }
|
||||
.switch-toggle.on::after { left: 18px; }
|
||||
.addr-form-actions { display: flex; gap: 8px; margin-top: 12px; }
|
||||
.addr-form-actions .btn {
|
||||
flex: 1; height: 36px; border-radius: 18px; border: none; font-size: 13px;
|
||||
font-weight: 600; cursor: pointer;
|
||||
}
|
||||
.addr-form-actions .btn-cancel { background: #f5f5f5; color: #666; }
|
||||
.addr-form-actions .btn-save { background: #1677ff; color: #fff; }
|
||||
|
||||
/* 新增按钮 */
|
||||
.add-btn-wrap { margin: 16px 16px 0; }
|
||||
.add-addr-btn {
|
||||
width: 100%; padding: 14px 0; border-radius: 12px; border: 1.5px dashed #1677ff;
|
||||
background: #fff; color: #1677ff; font-size: 14px; font-weight: 600; cursor: pointer;
|
||||
display: flex; align-items: center; justify-content: center; gap: 4px;
|
||||
}
|
||||
|
||||
/* 空状态 */
|
||||
.empty-state { text-align: center; padding: 60px 20px; color: #ccc; }
|
||||
.empty-state .empty-icon { font-size: 48px; margin-bottom: 12px; }
|
||||
.empty-state .empty-text { font-size: 14px; }
|
||||
|
||||
.hidden { display: none !important; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="phone-shell">
|
||||
<div class="status-bar">
|
||||
<span class="time">09:41</span>
|
||||
<div class="icons"><span>📶</span><span>WiFi</span><span>🔋</span></div>
|
||||
</div>
|
||||
<div class="nav-bar">
|
||||
<a class="back" href="me-home.html">‹</a>
|
||||
<span class="title">收货地址</span>
|
||||
</div>
|
||||
<div class="page-content" id="pageContent">
|
||||
<!-- 地址列表 -->
|
||||
<div class="addr-card" data-id="1">
|
||||
<div class="ac-top">
|
||||
<span class="ac-name">张三</span>
|
||||
<span class="ac-phone">138****6688</span>
|
||||
<span class="ac-default">默认</span>
|
||||
</div>
|
||||
<div class="ac-detail">渝北区龙湖路123号4栋1单元1801</div>
|
||||
<div class="ac-actions">
|
||||
<button class="ac-btn primary" data-action="edit">编辑</button>
|
||||
<button class="ac-btn" data-action="delete">删除</button>
|
||||
</div>
|
||||
<!-- 编辑表单 -->
|
||||
<div class="addr-form">
|
||||
<div class="form-row">
|
||||
<div class="form-label">收货人 <span class="required">*</span></div>
|
||||
<input class="form-input" value="张三" placeholder="请输入收货人姓名">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="form-label">手机号 <span class="required">*</span></div>
|
||||
<input class="form-input" value="138****6688" placeholder="请输入11位手机号">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="form-label">所在地区 <span class="required">*</span></div>
|
||||
<input class="form-input" value="重庆市 渝北区" placeholder="省 / 市 / 区" readonly>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="form-label">详细地址 <span class="required">*</span></div>
|
||||
<textarea class="form-textarea" placeholder="街道、楼牌号等">渝北区龙湖路123号4栋1单元1801</textarea>
|
||||
</div>
|
||||
<div class="form-row form-switch">
|
||||
<span>设为默认收货地址</span>
|
||||
<button class="switch-toggle on"></button>
|
||||
</div>
|
||||
<div class="addr-form-actions">
|
||||
<button class="btn btn-cancel" data-action="cancel">取消</button>
|
||||
<button class="btn btn-save" data-action="save">保存</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="addr-card" data-id="2">
|
||||
<div class="ac-top">
|
||||
<span class="ac-name">张三</span>
|
||||
<span class="ac-phone">138****6688</span>
|
||||
</div>
|
||||
<div class="ac-detail">南岸区江南大道28号写字楼12层</div>
|
||||
<div class="ac-actions">
|
||||
<button class="ac-btn primary" data-action="edit">编辑</button>
|
||||
<button class="ac-btn" data-action="delete">删除</button>
|
||||
</div>
|
||||
<div class="addr-form">
|
||||
<div class="form-row">
|
||||
<div class="form-label">收货人 <span class="required">*</span></div>
|
||||
<input class="form-input" value="张三" placeholder="请输入收货人姓名">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="form-label">手机号 <span class="required">*</span></div>
|
||||
<input class="form-input" value="138****6688" placeholder="请输入11位手机号">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="form-label">所在地区 <span class="required">*</span></div>
|
||||
<input class="form-input" value="重庆市 南岸区" placeholder="省 / 市 / 区" readonly>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="form-label">详细地址 <span class="required">*</span></div>
|
||||
<textarea class="form-textarea" placeholder="街道、楼牌号等">南岸区江南大道28号写字楼12层</textarea>
|
||||
</div>
|
||||
<div class="form-row form-switch">
|
||||
<span>设为默认收货地址</span>
|
||||
<button class="switch-toggle"></button>
|
||||
</div>
|
||||
<div class="addr-form-actions">
|
||||
<button class="btn btn-cancel" data-action="cancel">取消</button>
|
||||
<button class="btn btn-save" data-action="save">保存</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="addr-card" data-id="3">
|
||||
<div class="ac-top">
|
||||
<span class="ac-name">李四</span>
|
||||
<span class="ac-phone">139****1234</span>
|
||||
</div>
|
||||
<div class="ac-detail">渝北区黄山大道中段55号2栋802</div>
|
||||
<div class="ac-actions">
|
||||
<button class="ac-btn primary" data-action="edit">编辑</button>
|
||||
<button class="ac-btn" data-action="delete">删除</button>
|
||||
</div>
|
||||
<div class="addr-form">
|
||||
<div class="form-row">
|
||||
<div class="form-label">收货人 <span class="required">*</span></div>
|
||||
<input class="form-input" value="李四" placeholder="请输入收货人姓名">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="form-label">手机号 <span class="required">*</span></div>
|
||||
<input class="form-input" value="139****1234" placeholder="请输入11位手机号">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="form-label">所在地区 <span class="required">*</span></div>
|
||||
<input class="form-input" value="重庆市 渝北区" placeholder="省 / 市 / 区" readonly>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="form-label">详细地址 <span class="required">*</span></div>
|
||||
<textarea class="form-textarea" placeholder="街道、楼牌号等">渝北区黄山大道中段55号2栋802</textarea>
|
||||
</div>
|
||||
<div class="form-row form-switch">
|
||||
<span>设为默认收货地址</span>
|
||||
<button class="switch-toggle"></button>
|
||||
</div>
|
||||
<div class="addr-form-actions">
|
||||
<button class="btn btn-cancel" data-action="cancel">取消</button>
|
||||
<button class="btn btn-save" data-action="save">保存</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 新增按钮 -->
|
||||
<div class="add-btn-wrap" id="addBtnWrap">
|
||||
<button class="add-addr-btn" id="showAddBtn">+ 新增收货地址</button>
|
||||
</div>
|
||||
|
||||
<!-- 新增地址表单 -->
|
||||
<div class="addr-card hidden" id="addCard">
|
||||
<div class="ac-top">
|
||||
<span class="ac-name" style="color:#999;">新地址</span>
|
||||
</div>
|
||||
<div class="addr-form show" id="addForm">
|
||||
<div class="form-row">
|
||||
<div class="form-label">收货人 <span class="required">*</span></div>
|
||||
<input class="form-input" placeholder="请输入收货人姓名">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="form-label">手机号 <span class="required">*</span></div>
|
||||
<input class="form-input" placeholder="请输入11位手机号">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="form-label">所在地区 <span class="required">*</span></div>
|
||||
<input class="form-input" placeholder="省 / 市 / 区" readonly>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="form-label">详细地址 <span class="required">*</span></div>
|
||||
<textarea class="form-textarea" placeholder="街道、楼牌号等"></textarea>
|
||||
</div>
|
||||
<div class="form-row form-switch">
|
||||
<span>设为默认收货地址</span>
|
||||
<button class="switch-toggle" id="addDefaultToggle"></button>
|
||||
</div>
|
||||
<div class="addr-form-actions">
|
||||
<button class="btn btn-cancel" id="addCancelBtn">取消</button>
|
||||
<button class="btn btn-save" id="addSaveBtn">保存</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="home-indicator"></div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
/* 编辑/删除按钮事件委托 */
|
||||
document.getElementById('pageContent').addEventListener('click', function(e) {
|
||||
var actionBtn = e.target.closest('[data-action]');
|
||||
if (!actionBtn) {
|
||||
/* 点击开关切换 */
|
||||
var toggle = e.target.closest('.switch-toggle');
|
||||
if (toggle) { toggle.classList.toggle('on'); }
|
||||
return;
|
||||
}
|
||||
|
||||
var card = actionBtn.closest('.addr-card');
|
||||
var action = actionBtn.dataset.action;
|
||||
|
||||
if (action === 'edit') {
|
||||
/* 展开/收起编辑表单 */
|
||||
var form = card.querySelector('.addr-form');
|
||||
var isOpen = form.classList.contains('show');
|
||||
/* 关闭所有其他表单 */
|
||||
document.querySelectorAll('.addr-form.show').forEach(function(f) { f.classList.remove('show'); });
|
||||
if (!isOpen) { form.classList.add('show'); }
|
||||
} else if (action === 'delete') {
|
||||
/* 原型演示:直接移除卡片 */
|
||||
if (confirm('确定要删除该收货地址吗?')) {
|
||||
card.remove();
|
||||
checkEmpty();
|
||||
}
|
||||
} else if (action === 'cancel') {
|
||||
/* 取消编辑:关闭表单 */
|
||||
card.querySelector('.addr-form').classList.remove('show');
|
||||
} else if (action === 'save') {
|
||||
/* 保存编辑:同步表单数据到卡片并关闭 */
|
||||
var form = card.querySelector('.addr-form');
|
||||
var inputs = form.querySelectorAll('.form-input, .form-textarea');
|
||||
var name = inputs[0].value || '未命名';
|
||||
var phone = inputs[1].value || '';
|
||||
var area = inputs[2].value || '';
|
||||
var detail = inputs[3].value || '';
|
||||
var isDefault = form.querySelector('.switch-toggle').classList.contains('on');
|
||||
/* 更新卡片显示 */
|
||||
card.querySelector('.ac-name').textContent = name;
|
||||
card.querySelector('.ac-phone').textContent = phone;
|
||||
card.querySelector('.ac-detail').textContent = area ? area + ' ' + detail : detail;
|
||||
/* 默认地址标识 */
|
||||
var defaultTag = card.querySelector('.ac-default');
|
||||
if (isDefault) {
|
||||
/* 其他卡片移除默认 */
|
||||
document.querySelectorAll('.ac-default').forEach(function(t) { t.style.display = 'none'; });
|
||||
if (defaultTag) { defaultTag.style.display = ''; }
|
||||
else {
|
||||
var tag = document.createElement('span');
|
||||
tag.className = 'ac-default';
|
||||
tag.textContent = '默认';
|
||||
card.querySelector('.ac-top').appendChild(tag);
|
||||
}
|
||||
} else {
|
||||
if (defaultTag) defaultTag.style.display = 'none';
|
||||
}
|
||||
form.classList.remove('show');
|
||||
}
|
||||
});
|
||||
|
||||
/* 显示新增表单 */
|
||||
document.getElementById('showAddBtn').addEventListener('click', function() {
|
||||
document.getElementById('addCard').classList.remove('hidden');
|
||||
document.getElementById('addBtnWrap').classList.add('hidden');
|
||||
});
|
||||
|
||||
/* 新增表单默认开关 */
|
||||
document.getElementById('addDefaultToggle').addEventListener('click', function() {
|
||||
this.classList.toggle('on');
|
||||
});
|
||||
|
||||
/* 取消新增 */
|
||||
document.getElementById('addCancelBtn').addEventListener('click', function() {
|
||||
document.getElementById('addCard').classList.add('hidden');
|
||||
document.getElementById('addBtnWrap').classList.remove('hidden');
|
||||
/* 清空表单 */
|
||||
var form = document.getElementById('addForm');
|
||||
form.querySelectorAll('.form-input, .form-textarea').forEach(function(el) { el.value = ''; });
|
||||
form.querySelector('.switch-toggle').classList.remove('on');
|
||||
});
|
||||
|
||||
/* 保存新增 */
|
||||
document.getElementById('addSaveBtn').addEventListener('click', function() {
|
||||
var form = document.getElementById('addForm');
|
||||
var inputs = form.querySelectorAll('.form-input, .form-textarea');
|
||||
var name = inputs[0].value || '新地址';
|
||||
var phone = inputs[1].value || '';
|
||||
var area = inputs[2].value || '';
|
||||
var detail = inputs[3].value || '';
|
||||
var isDefault = form.querySelector('.switch-toggle').classList.contains('on');
|
||||
|
||||
/* 生成新卡片 */
|
||||
var html = '<div class="addr-card" data-id="' + Date.now() + '">'
|
||||
+ '<div class="ac-top">'
|
||||
+ '<span class="ac-name">' + name + '</span>'
|
||||
+ '<span class="ac-phone">' + phone + '</span>'
|
||||
+ (isDefault ? '<span class="ac-default">默认</span>' : '')
|
||||
+ '</div>'
|
||||
+ '<div class="ac-detail">' + (area ? area + ' ' : '') + detail + '</div>'
|
||||
+ '<div class="ac-actions">'
|
||||
+ '<button class="ac-btn primary" data-action="edit">编辑</button>'
|
||||
+ '<button class="ac-btn" data-action="delete">删除</button>'
|
||||
+ '</div>'
|
||||
+ '<div class="addr-form">'
|
||||
+ '<div class="form-row"><div class="form-label">收货人 <span class="required">*</span></div><input class="form-input" value="' + name + '" placeholder="请输入收货人姓名"></div>'
|
||||
+ '<div class="form-row"><div class="form-label">手机号 <span class="required">*</span></div><input class="form-input" value="' + phone + '" placeholder="请输入11位手机号"></div>'
|
||||
+ '<div class="form-row"><div class="form-label">所在地区 <span class="required">*</span></div><input class="form-input" value="' + area + '" placeholder="省 / 市 / 区" readonly></div>'
|
||||
+ '<div class="form-row"><div class="form-label">详细地址 <span class="required">*</span></div><textarea class="form-textarea" placeholder="街道、楼牌号等">' + detail + '</textarea></div>'
|
||||
+ '<div class="form-row form-switch"><span>设为默认收货地址</span><button class="switch-toggle' + (isDefault ? ' on' : '') + '"></button></div>'
|
||||
+ '<div class="addr-form-actions"><button class="btn btn-cancel" data-action="cancel">取消</button><button class="btn btn-save" data-action="save">保存</button></div>'
|
||||
+ '</div>'
|
||||
+ '</div>';
|
||||
|
||||
/* 如果设为默认,移除其他地址的默认标记 */
|
||||
if (isDefault) {
|
||||
document.querySelectorAll('.ac-default').forEach(function(t) { t.style.display = 'none'; });
|
||||
}
|
||||
|
||||
/* 插入到新增按钮之前 */
|
||||
document.getElementById('addBtnWrap').insertAdjacentHTML('beforebegin', html);
|
||||
|
||||
/* 隐藏新增表单并重置 */
|
||||
document.getElementById('addCard').classList.add('hidden');
|
||||
document.getElementById('addBtnWrap').classList.remove('hidden');
|
||||
inputs.forEach(function(el) { el.value = ''; });
|
||||
form.querySelector('.switch-toggle').classList.remove('on');
|
||||
checkEmpty();
|
||||
});
|
||||
|
||||
/* 检查地址列表是否为空 */
|
||||
function checkEmpty() {
|
||||
var cards = document.querySelectorAll('.addr-card:not(#addCard)');
|
||||
if (cards.length === 0) {
|
||||
var emptyHtml = '<div class="empty-state" id="emptyHint"><div class="empty-icon">📭</div><div class="empty-text">暂无收货地址</div></div>';
|
||||
document.getElementById('addBtnWrap').insertAdjacentHTML('beforebegin', emptyHtml);
|
||||
} else {
|
||||
var hint = document.getElementById('emptyHint');
|
||||
if (hint) hint.remove();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -381,17 +381,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 9. 营养目标 保留 -->
|
||||
<div class="section" id="goalSection" onclick="openGoalModal()" style="cursor:pointer;">
|
||||
<div class="sec-header">
|
||||
<span class="sec-title"><span class="sec-icon">🎯</span>营养目标</span>
|
||||
<span class="sec-action">编辑 ›</span>
|
||||
</div>
|
||||
<div class="goal-item"><span class="g-label">每日热量</span><span class="g-value" id="viewGoalCalorie">2000 kcal</span></div>
|
||||
<div class="goal-item"><span class="g-label">蛋白质</span><span class="g-value" id="viewGoalProtein">≥60g</span></div>
|
||||
<div class="goal-item"><span class="g-label">膳食纤维</span><span class="g-value" id="viewGoalFiber">≥25g</span></div>
|
||||
<div class="goal-item"><span class="g-label">饮水量</span><span class="g-value" id="viewGoalWater">≥2000ml</span></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="home-indicator"></div>
|
||||
|
||||
@@ -585,34 +574,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ========== 营养目标编辑弹窗 ========== -->
|
||||
<div class="modal-mask" id="goalModal">
|
||||
<div class="modal-panel" onclick="event.stopPropagation()">
|
||||
<div class="modal-header">
|
||||
<span class="m-cancel" onclick="closeModal('goalModal')">取消</span>
|
||||
<span class="m-title">编辑营养目标</span>
|
||||
<span class="m-save" onclick="saveGoalModal()">保存</span>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="m-goal-row">
|
||||
<span class="mg-label">每日热量</span>
|
||||
<span class="mg-input-wrap"><input type="number" id="inputCalorie" value="2000"><span class="mg-unit">kcal</span></span>
|
||||
</div>
|
||||
<div class="m-goal-row">
|
||||
<span class="mg-label">蛋白质(≥)</span>
|
||||
<span class="mg-input-wrap"><input type="number" id="inputProtein" value="60"><span class="mg-unit">g</span></span>
|
||||
</div>
|
||||
<div class="m-goal-row">
|
||||
<span class="mg-label">膳食纤维(≥)</span>
|
||||
<span class="mg-input-wrap"><input type="number" id="inputFiber" value="25"><span class="mg-unit">g</span></span>
|
||||
</div>
|
||||
<div class="m-goal-row">
|
||||
<span class="mg-label">饮水量(≥)</span>
|
||||
<span class="mg-input-wrap"><input type="number" id="inputWater" value="2000"><span class="mg-unit">ml</span></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
/* ========== 通用弹窗控制 ========== */
|
||||
@@ -764,21 +725,6 @@
|
||||
alert('已保存(原型演示)');
|
||||
}
|
||||
|
||||
/* ========== 营养目标 ========== */
|
||||
function openGoalModal() { document.getElementById('goalModal').classList.add('active'); }
|
||||
function saveGoalModal() {
|
||||
var cal = document.getElementById('inputCalorie').value || '0';
|
||||
var pro = document.getElementById('inputProtein').value || '0';
|
||||
var fib = document.getElementById('inputFiber').value || '0';
|
||||
var wat = document.getElementById('inputWater').value || '0';
|
||||
document.getElementById('viewGoalCalorie').textContent = cal + ' kcal';
|
||||
document.getElementById('viewGoalProtein').textContent = '≥' + pro + 'g';
|
||||
document.getElementById('viewGoalFiber').textContent = '≥' + fib + 'g';
|
||||
document.getElementById('viewGoalWater').textContent = '≥' + wat + 'ml';
|
||||
closeModal('goalModal');
|
||||
alert('已保存(原型演示)');
|
||||
}
|
||||
|
||||
/* ========== 通用回写:将编辑态标签同步到页面展示区 ========== */
|
||||
// viewId: 展示区容器id; groupId: 编辑态分组id; cls: 展示态span的class; asText: true则拼成文本而非标签
|
||||
function syncGroupBack(viewId, groupId, cls, asText) {
|
||||
@@ -802,7 +748,7 @@
|
||||
}
|
||||
|
||||
/* ========== 点击遮罩层空白处关闭弹窗 ========== */
|
||||
['bodyModal','diseaseModal','tasteModal','tabooModal','dishModal','momModal','goalModal'].forEach(function(id) {
|
||||
['bodyModal','diseaseModal','tasteModal','tabooModal','dishModal','momModal'].forEach(function(id) {
|
||||
var el = document.getElementById(id);
|
||||
if (el) el.addEventListener('click', function() { closeModal(id); });
|
||||
});
|
||||
|
||||
@@ -133,6 +133,7 @@
|
||||
<div class="menu-group">
|
||||
<a class="menu-item" href="me-health.html"><span class="m-icon">💚</span><span class="m-label">健康档案</span><span class="m-arrow">›</span></a>
|
||||
<a class="menu-item" href="me-orders.html"><span class="m-icon">📋</span><span class="m-label">我的订单</span><span class="m-badge">2</span><span class="m-arrow">›</span></a>
|
||||
<a class="menu-item" href="me-address.html"><span class="m-icon">📍</span><span class="m-label">收货地址</span><span class="m-arrow">›</span></a>
|
||||
<a class="menu-item" href="me-favorites.html"><span class="m-icon">⭐</span><span class="m-label">收藏食谱</span><span class="m-arrow">›</span></a>
|
||||
<a class="menu-item" href="me-wallet.html"><span class="m-icon">💰</span><span class="m-label">我的余额</span><span class="m-arrow">›</span></a>
|
||||
<a class="menu-item" href="me-vip.html"><span class="m-icon">👑</span><span class="m-label">会员中心</span><span class="m-arrow">›</span></a>
|
||||
|
||||
@@ -56,6 +56,7 @@
|
||||
.ing-name { font-size: 12px; font-weight: 500; color: #444; }
|
||||
.ing-code { font-size: 9px; color: #bbb; font-family: monospace; margin-top: 1px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||
.ing-ok { font-size: 10px; padding: 1px 5px; border-radius: 5px; background: #f6ffed; color: #52c41a; flex-shrink: 0; white-space: nowrap; }
|
||||
.ing-role { font-size: 10px; padding: 1px 5px; border-radius: 4px; flex-shrink: 0; white-space: nowrap; background: #f5f5f5; color: #999; }
|
||||
.ing-trace { padding: 3px 8px; border-radius: 8px; border: 1px solid #1677ff; background: #fff; color: #1677ff; font-size: 10px; cursor: pointer; flex-shrink: 0; white-space: nowrap; text-decoration: none; }
|
||||
/* 营养建议 */
|
||||
.advice-card { background: #fff; border-radius: 12px; padding: 12px 14px; margin: 0 16px 24px; }
|
||||
@@ -124,16 +125,11 @@
|
||||
<div class="oh-stat"><div class="sv" style="color:#1677ff">3</div><div class="sl">菜品数</div></div>
|
||||
<div class="oh-stat"><div class="sv" style="color:#555">442</div><div class="sl">总热量kcal</div></div>
|
||||
</div>
|
||||
<div class="oh-tags">
|
||||
<span class="oh-tag" style="background:#e6f4ff;color:#1677ff">点餐取餐</span>
|
||||
<span class="oh-tag" style="background:#f5f5f5;color:#666">A区中餐线</span>
|
||||
<span class="oh-tag" style="background:#f5f5f5;color:#666">余额支付</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 净菜包专属:履约信息 + 状态时间线(默认隐藏) -->
|
||||
<!-- 净菜包专属:配送信息 + 状态时间线(默认隐藏) -->
|
||||
<div class="fulfill-section hidden" id="cleanExtra">
|
||||
<div class="sec-card">
|
||||
<div class="sec-title">📦 履约信息</div>
|
||||
<div class="sec-title">📦 配送信息</div>
|
||||
<div class="info-row">
|
||||
<span class="ir-label">取货方式</span>
|
||||
<span class="ir-value">🚚 配送到家</span>
|
||||
@@ -293,7 +289,22 @@
|
||||
}
|
||||
|
||||
var type = getQuery('type') === 'clean' ? 'clean' : 'meal';
|
||||
/* 净菜包订单状态:delivering=待配送 / shipped=已发货 / done=已完成;缺省按待配送处理 */
|
||||
var rawStatus = getQuery('status');
|
||||
var status = ['delivering', 'shipped', 'done'].indexOf(rawStatus) >= 0 ? rawStatus : 'delivering';
|
||||
|
||||
/* 是否展示食材来源与溯源按钮:仅 已发货 / 已完成 可见 */
|
||||
var showTrace = status === 'shipped' || status === 'done';
|
||||
|
||||
if (type === 'clean') {
|
||||
/* 状态徽标:文案与配色随 status 切换 */
|
||||
var badgeMap = {
|
||||
delivering: { text: '🚚 待配送', bg: '#e6f4ff', color: '#1677ff' },
|
||||
shipped: { text: '🚚 配送中', bg: '#fff7e6', color: '#fa8c16' },
|
||||
done: { text: '✅ 已完成', bg: '#f6ffed', color: '#52c41a' }
|
||||
};
|
||||
var b = badgeMap[status];
|
||||
|
||||
/* 替换订单头部:净菜包订单基本信息 */
|
||||
document.getElementById('orderHeader').innerHTML =
|
||||
'<div class="oh-top">'
|
||||
@@ -301,26 +312,62 @@
|
||||
+ '<div class="oh-date">2026-04-29 午餐时段配送</div>'
|
||||
+ '<div class="oh-id">CL-20260428-017</div>'
|
||||
+ '</div>'
|
||||
+ '<span class="oh-badge" style="background:#e6f4ff;color:#1677ff;">🚚 待配送</span>'
|
||||
+ '<span class="oh-badge" style="background:' + b.bg + ';color:' + b.color + ';">' + b.text + '</span>'
|
||||
+ '</div>'
|
||||
+ '<div class="oh-stats">'
|
||||
+ '<div class="oh-stat"><div class="sv" style="color:#fa8c16">890</div><div class="sl">总热量kcal</div></div>'
|
||||
+ '<div class="oh-stat"><div class="sv" style="color:#f5222d">¥79</div><div class="sl">消费金额</div></div>'
|
||||
+ '<div class="oh-stat"><div class="sv" style="color:#1677ff">2</div><div class="sl">净菜包种类</div></div>'
|
||||
+ '<div class="oh-stat"><div class="sv" style="color:#722ed1">1.0kg</div><div class="sl">总净重</div></div>'
|
||||
+ '</div>'
|
||||
+ '<div class="oh-tags">'
|
||||
+ '<span class="oh-tag" style="background:#fff7e6;color:#fa8c16">预售订单</span>'
|
||||
+ '<span class="oh-tag" style="background:#e6f4ff;color:#1677ff">配送到家</span>'
|
||||
+ '<span class="oh-tag" style="background:#f5f5f5;color:#666">余额支付</span>'
|
||||
+ '</div>';
|
||||
|
||||
/* 显示履约信息 + 订单进度时间线 */
|
||||
/* 显示配送信息 + 订单进度时间线 */
|
||||
document.getElementById('cleanExtra').classList.remove('hidden');
|
||||
|
||||
/* 替换菜品明细:餐品 → 净菜包明细 */
|
||||
/* 替换菜品明细:餐品 → 净菜包明细;待配送状态下不展示食材来源/溯源 */
|
||||
var dishTitle = showTrace ? '净菜包明细 · 食材 · 溯源' : '净菜包明细';
|
||||
|
||||
/* 宫保鸡丁净菜包:食材明细(已发货/已完成 有溯源按钮,待配送无溯源按钮;均含克重) */
|
||||
var gongBaoIngRows = [
|
||||
{ name: '鸡胸肉', weight: '150g', code: 'NC-PROC-JBR-20260422-01', role: '主材' },
|
||||
{ name: '花生米', weight: '30g', code: 'ST-EX-HS05-PT-HSMI-050K-20260420-001', role: '辅材' }
|
||||
];
|
||||
var gongBaoIng = showTrace
|
||||
? '<div class="ing-section">'
|
||||
+ '<div class="ing-label">食材来源</div>'
|
||||
+ gongBaoIngRows.map(function(r) {
|
||||
return '<div class="ing-row"><div class="ing-dot"></div><div class="ing-info"><div class="ing-name">' + r.name + ' ' + r.weight + '</div><div class="ing-code">' + r.code + '</div></div><span class="ing-ok">✅合格</span><a class="ing-trace" href="trace-detail.html">🔗溯源</a></div>';
|
||||
}).join('')
|
||||
+ '</div>'
|
||||
: '<div class="ing-section">'
|
||||
+ '<div class="ing-label">食材明细</div>'
|
||||
+ gongBaoIngRows.map(function(r) {
|
||||
return '<div class="ing-row"><div class="ing-dot"></div><div class="ing-info"><div class="ing-name">' + r.name + ' ' + r.weight + '</div></div><span class="ing-role">' + r.role + '</span></div>';
|
||||
}).join('')
|
||||
+ '</div>';
|
||||
|
||||
/* 低脂控糖套餐净菜包:食材明细(同上规则) */
|
||||
var lowFatIngRows = [
|
||||
{ name: '鸡胸肉', weight: '150g', code: 'NC-PROC-JBR-20260422-01', role: '主材' },
|
||||
{ name: '西兰花', weight: '80g', code: 'ST-EX-LY01-VG-XLHU-080K-20260416-001', role: '辅材' },
|
||||
{ name: '糙米', weight: '120g', code: 'ST-EX-LY03-DG-CAMI-500K-20260413-002', role: '主材' }
|
||||
];
|
||||
var lowFatIng = showTrace
|
||||
? '<div class="ing-section">'
|
||||
+ '<div class="ing-label">食材来源</div>'
|
||||
+ lowFatIngRows.map(function(r) {
|
||||
return '<div class="ing-row"><div class="ing-dot"></div><div class="ing-info"><div class="ing-name">' + r.name + ' ' + r.weight + '</div><div class="ing-code">' + r.code + '</div></div><span class="ing-ok">✅合格</span><a class="ing-trace" href="trace-detail.html">🔗溯源</a></div>';
|
||||
}).join('')
|
||||
+ '</div>'
|
||||
: '<div class="ing-section">'
|
||||
+ '<div class="ing-label">食材明细</div>'
|
||||
+ lowFatIngRows.map(function(r) {
|
||||
return '<div class="ing-row"><div class="ing-dot"></div><div class="ing-info"><div class="ing-name">' + r.name + ' ' + r.weight + '</div></div><span class="ing-role">' + r.role + '</span></div>';
|
||||
}).join('')
|
||||
+ '</div>';
|
||||
|
||||
document.getElementById('dishSection').innerHTML =
|
||||
'<div class="dish-sec-title">净菜包明细 · 食材 · 溯源</div>'
|
||||
'<div class="dish-sec-title">' + dishTitle + '</div>'
|
||||
+ '<div class="dish-card">'
|
||||
+ '<div class="dish-head">'
|
||||
+ '<div class="dish-icon">🍗</div>'
|
||||
@@ -333,11 +380,7 @@
|
||||
+ '</div>'
|
||||
+ '<span class="dish-price">¥44</span>'
|
||||
+ '</div>'
|
||||
+ '<div class="ing-section">'
|
||||
+ '<div class="ing-label">食材来源</div>'
|
||||
+ '<div class="ing-row"><div class="ing-dot"></div><div class="ing-info"><div class="ing-name">鸡胸肉</div><div class="ing-code">NC-PROC-JBR-20260422-01</div></div><span class="ing-ok">✅合格</span><a class="ing-trace" href="trace-detail.html">🔗溯源</a></div>'
|
||||
+ '<div class="ing-row"><div class="ing-dot"></div><div class="ing-info"><div class="ing-name">花生米</div><div class="ing-code">ST-EX-HS05-PT-HSMI-050K-20260420-001</div></div><span class="ing-ok">✅合格</span><a class="ing-trace" href="trace-detail.html">🔗溯源</a></div>'
|
||||
+ '</div>'
|
||||
+ gongBaoIng
|
||||
+ '</div>'
|
||||
+ '<div class="dish-card">'
|
||||
+ '<div class="dish-head">'
|
||||
@@ -351,17 +394,51 @@
|
||||
+ '</div>'
|
||||
+ '<span class="dish-price">¥35</span>'
|
||||
+ '</div>'
|
||||
+ '<div class="ing-section">'
|
||||
+ '<div class="ing-label">食材来源</div>'
|
||||
+ '<div class="ing-row"><div class="ing-dot"></div><div class="ing-info"><div class="ing-name">鸡胸肉</div><div class="ing-code">NC-PROC-JBR-20260422-01</div></div><span class="ing-ok">✅合格</span><a class="ing-trace" href="trace-detail.html">🔗溯源</a></div>'
|
||||
+ '<div class="ing-row"><div class="ing-dot"></div><div class="ing-info"><div class="ing-name">西兰花</div><div class="ing-code">ST-EX-LY01-VG-XLHU-080K-20260416-001</div></div><span class="ing-ok">✅合格</span><a class="ing-trace" href="trace-detail.html">🔗溯源</a></div>'
|
||||
+ '<div class="ing-row"><div class="ing-dot"></div><div class="ing-info"><div class="ing-name">糙米</div><div class="ing-code">ST-EX-LY03-DG-CAMI-500K-20260413-002</div></div><span class="ing-ok">✅合格</span><a class="ing-trace" href="trace-detail.html">🔗溯源</a></div>'
|
||||
+ '</div>'
|
||||
+ lowFatIng
|
||||
+ '</div>'
|
||||
+ '<div class="advice-card" style="margin:0;">'
|
||||
+ '<div class="advice-title">🍳 烹制提示</div>'
|
||||
+ '<div class="advice-text" style="color:#1677ff;">宫保鸡丁净菜包:热锅冷油下鸡丁滑炒至变色,加入配料包翻炒 2 分钟即可出锅;糙米饭需另行准备。</div>'
|
||||
+ '</div>';
|
||||
|
||||
/* 订单进度时间线:按状态高亮对应节点 */
|
||||
renderCleanTimeline(status);
|
||||
}
|
||||
|
||||
/* 渲染净菜包订单进度时间线 */
|
||||
function renderCleanTimeline(status) {
|
||||
var states = ['submitted', 'prepared', 'delivering', 'shipping', 'arrived'];
|
||||
var activeIdx;
|
||||
if (status === 'delivering') {
|
||||
activeIdx = 2; /* 高亮:待配送 */
|
||||
} else if (status === 'shipped') {
|
||||
activeIdx = 3; /* 高亮:配送中 */
|
||||
} else { /* done */
|
||||
activeIdx = 4; /* 全部完成:已送达 */
|
||||
}
|
||||
var nodes = [
|
||||
{ title: '订单提交', time: '2026-04-28 14:23' },
|
||||
{ title: '备货完成', time: '2026-04-28 15:00 截单' },
|
||||
{ title: '待配送', time: '预计 2026-04-29 11:00 开始配送' },
|
||||
{ title: '配送中', time: status === 'shipped' ? '骑手已取货,预计 30 分钟内送达' : '-' },
|
||||
{ title: '已送达', time: status === 'done' ? '2026-04-29 12:08 送达' : '-' }
|
||||
];
|
||||
var html = '';
|
||||
for (var i = 0; i < nodes.length; i++) {
|
||||
var cls = '';
|
||||
if (i < activeIdx) cls = 'done';
|
||||
else if (i === activeIdx) cls = i === nodes.length - 1 ? 'done' : 'active';
|
||||
else if (status === 'done' && i === activeIdx) cls = 'done';
|
||||
html += '<div class="tl-item ' + cls + '">'
|
||||
+ '<div class="tl-dot"></div>'
|
||||
+ '<div class="tl-content">'
|
||||
+ '<div class="tl-title">' + nodes[i].title + '</div>'
|
||||
+ '<div class="tl-time">' + nodes[i].time + '</div>'
|
||||
+ '</div>'
|
||||
+ '</div>';
|
||||
}
|
||||
var timelineWrap = document.querySelector('#cleanExtra .timeline');
|
||||
if (timelineWrap) timelineWrap.innerHTML = html;
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
<div class="items">低脂鸡胸肉沙拉 ×1、杂粮饭 ×1、紫菜蛋花汤 ×1</div>
|
||||
<div class="card-bottom"><span class="total">¥ 28.5</span><span class="time">今天 11:32</span></div>
|
||||
</a>
|
||||
<a class="order-card" href="me-order-detail.html?type=clean">
|
||||
<a class="order-card" href="me-order-detail.html?type=clean&status=delivering">
|
||||
<div class="card-top">
|
||||
<div class="shop-row"><span class="shop">🥬 阳光食堂 · 净菜包订单</span><span class="type-tag clean">净菜包</span></div>
|
||||
<span class="status shipping">待配送</span>
|
||||
@@ -87,7 +87,7 @@
|
||||
<div class="items">全麦三明治 ×1、鲜榨橙汁 ×1</div>
|
||||
<div class="card-bottom"><span class="total">¥ 15.0</span><span class="time">今天 07:45</span></div>
|
||||
</a>
|
||||
<a class="order-card" href="me-order-detail.html?type=clean">
|
||||
<a class="order-card" href="me-order-detail.html?type=clean&status=done">
|
||||
<div class="card-top">
|
||||
<div class="shop-row"><span class="shop">🥬 阳光食堂 · 净菜包订单</span><span class="type-tag clean">净菜包</span></div>
|
||||
<span class="status">已完成</span>
|
||||
|
||||
Reference in New Issue
Block a user