首页/ mobileweb/ 小草咖啡轻食/ 代码预览

💻 代码预览 · 小草咖啡轻食

mw_food · 上传者 小草网络
← 返回详情
app.js · 约 11417 字符
1// 小草咖啡轻食 · 交互逻辑
2let cart = JSON.parse(localStorage.getItem('xc_coffee_cart') || '[]');
3let cartMode = 'pick';
4function saveCart(){ localStorage.setItem('xc_coffee_cart', JSON.stringify(cart)); }
5function cartCount(){ return cart.reduce((s,i)=>s+i.qty,0); }
6function cartTotal(){ return cart.reduce((s,i)=>s+i.price*i.qty,0); }
7function goodsCard(g){
8  return `<div class="goods-card" onclick="openSpec(${g.id})">
9    <div class="gc-img" style="background:${g.color}">
10      <span class="gc-tag badge ${g.sale?'badge-sale':g.new?'badge-new':'badge-hot'}">${g.sale?'🔥特惠':g.new?'🆕新品':'⭐热销'}</span>
11      ${g.emoji}
12    </div>
13    <div class="gc-body">
14      <div class="gc-name">${g.name}</div>
15      <div class="gc-desc">${g.desc}</div>
16      <div class="gc-bottom">
17        <span class="gc-price">¥${g.price}<small> <s>¥${g.origPrice}</s></small></span>
18        <button class="gc-add" onclick="event.stopPropagation();openSpec(${g.id})">+</button>
19      </div>
20    </div>
21  </div>`;
22}
23
24// 首页
25function renderIndex(){
26  document.getElementById('hot-goods').innerHTML = GOODS.filter(g=>g.hot).slice(0,4).map(goodsCard).join('');
27  document.getElementById('new-goods').innerHTML = GOODS.filter(g=>g.new).slice(0,4).map(goodsCard).join('');
28  document.getElementById('coupon-list').innerHTML = COUPONS.map(c=>`
29    <div class="coupon-card">
30      <div class="cc-left"><div class="cc-amount">${c.amount}</div><div class="cc-cond">${c.cond}</div></div>
31      <div class="cc-info"><div class="cc-name">${c.name}</div><div class="cc-time">🕐 ${c.time}</div></div>
32      <button class="gc-add" style="width:auto;padding:6px 14px;border-radius:18px;background:var(--primary);color:#fff;border:none;font-size:12px;cursor:pointer" onclick="alert('🎟️ 已领取${c.name}!')">领取</button>
33    </div>`).join('');
34}
35
36// 点单
37let catFilter = '咖啡', specGood = null, specQty = 1;
38let specSel = { size:0, sugar:2, ice:2, tops:[] };
39function renderMenu(){
40  document.getElementById('menu-side').innerHTML = CATS.map(c=>`<a href="javascript:void(0)" class="${c===catFilter?'active':''}" onclick="setCat('${c}')">${c}</a>`).join('');
41  const list = GOODS.filter(g=>g.cat===catFilter);
42  document.getElementById('menu-main').innerHTML = `<div class="mm-title">${catFilter}</div>` + list.map(g=>`
43    <div class="menu-item" onclick="openSpec(${g.id})">
44      <div class="mi-img" style="background:${g.color}">${g.emoji}</div>
45      <div class="mi-info">
46        <div class="mi-name">${g.name}</div>
47        <div class="mi-spec">${g.spec} · ${g.desc}</div>
48        <div class="mi-bottom">
49          <span class="mi-price">¥${g.price}</span>
50          <button class="mi-add" onclick="event.stopPropagation();openSpec(${g.id})">+</button>
51        </div>
52      </div>
53    </div>`).join('');
54  updateCartFloat();
55}
56function setCat(c){ catFilter=c; renderMenu(); }
57function updateCartFloat(){
58  const n=document.getElementById('cf-num'), t=document.getElementById('cf-total');
59  if(n){ n.textContent=cartCount(); t.textContent='¥'+cartTotal(); }
60}
61function openSpec(id){
62  specGood = GOODS.find(g=>g.id===id); if(!specGood) return;
63  specQty = 1; specSel = { size:0, sugar:2, ice:2, tops:[] };
64  document.getElementById('sp-name').textContent = specGood.name;
65  document.getElementById('sp-price').textContent = '¥'+specGood.price;
66  const chips = (arr,key,multi)=>{
67    return arr.map((v,i)=>{
68      const on = multi ? specSel[key].includes(i) : specSel[key]===i;
69      return `<span class="chip ${on?'active':''}" onclick="pickSpec(${i},'${key}',${multi})">${v}</span>`;
70    }).join('');
71  };
72  document.getElementById('sp-size').innerHTML = chips(SIZES,'size',false);
73  document.getElementById('sp-sugar').innerHTML = chips(SUGARS,'sugar',false);
74  document.getElementById('sp-ice').innerHTML = chips(ICES,'ice',false);
75  document.getElementById('sp-top').innerHTML = chips(TOPPINGS,'tops',true);
76  document.getElementById('sp-qty-num').textContent = 1;
77  document.getElementById('spec-mask').classList.add('show');
78  document.getElementById('spec-panel').classList.add('show');
79}
80function pickSpec(i,key,multi){
81  if(multi){ specSel[key].includes(i) ? specSel[key].splice(specSel[key].indexOf(i),1) : specSel[key].push(i); }
82  else { specSel[key]=i; }
83  openSpec(specGood.id);
84}
85function changeSpecQty(d){ specQty=Math.max(1,specQty+d); document.getElementById('sp-qty-num').textContent=specQty; }
86function confirmSpec(){
87  const tops = specSel.tops.map(i=>TOPPINGS[i]);
88  const price = specGood.price + tops.length*2;
89  cart.push({id:specGood.id, name:specGood.name, emoji:specGood.emoji, color:specGood.color,
90    spec:SIZES[specSel.size]+' · '+SUGARS[specSel.sugar]+' · '+ICES[specSel.ice]+(tops.length?' · +'+tops.join('/'):''),
91    price, qty:specQty});
92  saveCart(); closeSpec(); updateCartFloat();
93  alert('✅ 已加入购物车:'+specGood.name+' ×'+specQty);
94}
95function closeSpec(){
96  document.getElementById('spec-mask').classList.remove('show');
97  document.getElementById('spec-panel').classList.remove('show');
98}
99
100// 购物车
101function renderCart(){
102  const el=document.getElementById('cart-list');
103  if(!el) return;
104  if(!cart.length){
105    el.innerHTML='<div class="empty"><div class="eicon">🛒</div><div>购物车空空如也,去<a href="menu.html" style="color:var(--primary)">点单</a>吧~</div></div>';
106  } else {
107    el.innerHTML='<div style="background:#fff;border-radius:12px;margin:0 12px;overflow:hidden">'+cart.map((i,idx)=>`
108      <div class="cart-item">
109        <div class="ci-img" style="background:${i.color}">${i.emoji}</div>
110        <div class="ci-info">
111          <div class="ci-name">${i.name}</div>
112          <div class="ci-spec">${i.spec}</div>
113          <div class="ci-price">¥${i.price}</div>
114        </div>
115        <div class="qty"><button onclick="changeCartQty(${idx},-1)">−</button><span>${i.qty}</span><button onclick="changeCartQty(${idx},1)">+</button></div>
116      </div>`).join('')+'</div>';
117  }
118  document.getElementById('total-price').textContent='¥'+cartTotal();
119  document.getElementById('coupon-list').innerHTML = COUPONS.map(c=>`
120    <div class="coupon-card" style="margin:8px 12px">
121      <div class="cc-left"><div class="cc-amount">${c.amount}</div><div class="cc-cond">${c.cond}</div></div>
122      <div class="cc-info"><div class="cc-name">${c.name}</div><div class="cc-time">🕐 ${c.time}</div></div>
123      <span class="badge badge-sale" style="background:#fff7e6;color:var(--accent)">可用</span>
124    </div>`).join('');
125}
126function changeCartQty(idx,d){
127  cart[idx].qty+=d;
128  if(cart[idx].qty<=0) cart.splice(idx,1);
129  saveCart(); renderCart();
130}
131function setMode(m){
132  cartMode=m;
133  document.getElementById('mode-pick').classList.toggle('active',m==='pick');
134  document.getElementById('mode-delivery').classList.toggle('active',m==='delivery');
135}
136function checkout(){
137  if(!cart.length){ alert('购物车为空'); return; }
138  const remark=document.getElementById('remark-input').value;
139  const code='A'+Math.floor(100+Math.random()*900);
140  alert(`✅ 下单成功!\n\n${cartMode==='pick'?'到店自取 · 取餐码:'+code:'外卖配送 · 预计30分钟送达'}\n订单金额:¥${cartTotal()}\n备注:${remark||'无'}\n(演示页)`);
141  cart=[]; saveCart(); renderCart();
142}
143
144// 订单
145let orderFilter='';
146function renderOrders(){
147  const el=document.getElementById('order-list');
148  if(!el) return;
149  let orders=ORDERS;
150  if(orderFilter) orders=orders.filter(o=>o.status===orderFilter);
151  if(!orders.length){ el.innerHTML='<div class="empty"><div class="eicon">📦</div><div>暂无订单</div></div>'; return; }
152  el.innerHTML=orders.map(o=>{
153    const prog=PROGRESS[o.state], cur=o.state==='making'?2:o.state==='shipping'?2:3;
154    return `<div class="order-item">
155      <div class="oi-top"><span style="font-size:13px;color:#999">${o.id}</span><span class="oi-status">${o.status}</span></div>
156      <div class="oi-goods">
157        <div class="oi-img">${o.emoji}</div>
158        <div><div class="oi-name">${o.name}</div><div class="oi-spec">${o.spec}</div></div>
159      </div>
160      ${o.state==='making'?`<div class="pick-code"><span style="font-size:24px">🎫</span><div><div class="pc-num">${o.code}</div><div class="pc-tip">到店出示取餐码取餐</div></div></div>`:''}
161      <div class="progress">${prog.map((p,i)=>`<div class="pr-node ${i<=cur?'active':''}"><div class="pr-dot"></div>${p}</div>${i<prog.length-1?'<div class="pr-line"></div>':''}`).join('')}</div>
162      <div class="oi-bottom" style="margin-top:8px">
163        <span class="oi-total">实付 ¥${o.price}</span>
164        ${o.state==='done'?'<button class="oi-btn" style="padding:6px 14px;border-radius:20px;font-size:12px;border:none;background:#f5f5f5;color:#666;cursor:pointer" onclick="alert('⭐ 评价成功!')">去评价</button>':'<button class="oi-btn" style="padding:6px 14px;border-radius:20px;font-size:12px;border:none;background:linear-gradient(135deg,#7c4a21,#c07a3a);color:#fff;cursor:pointer" onclick="alert('🛒 再次购买')">再次购买</button>'}
165      </div>
166    </div>`;
167  }).join('');
168}
169function filterOrder(el,f){
170  orderFilter=f;
171  document.querySelectorAll('.status-bar a').forEach(a=>{a.style.color='#666';a.style.borderBottom='none';a.style.fontWeight='400'});
172  el.style.color='var(--primary)';el.style.borderBottom='2px solid var(--primary)';el.style.fontWeight='600';
173  renderOrders();
174}
175
176// 会员
177let rechargeSel=1;
178const RECHARGE=[{a:50,b:'送5'},{a:100,b:'送12'},{a:200,b:'送30'},{a:500,b:'送88'}];
179function renderMember(){
180  document.getElementById('mh-level').textContent='🏅 '+USER.level;
181  document.getElementById('mh-desc').textContent='银卡9折 · 生日双倍积分 · 专属新品尝鲜';
182  document.getElementById('mh-points').textContent=USER.points;
183  document.getElementById('mh-coupons').textContent=USER.coupons;
184  document.getElementById('bc-balance').textContent='¥'+USER.balance;
185  document.getElementById('bc-total').textContent='¥680';
186  document.getElementById('recharge-row').innerHTML=RECHARGE.map((r,i)=>`
187    <div class="rc-item ${i===rechargeSel?'active':''}" onclick="pickRecharge(${i})">
188      <div class="rc-amount">¥${r.a}</div><div class="rc-bonus">送${r.b}</div>
189    </div>`).join('');
190  document.getElementById('level-grid').innerHTML=LEVELS.map((l,i)=>`
191    <div class="level-card ${l.name===USER.level?'current':''}">
192      <div class="lc-icon">${l.icon}</div>
193      <div class="lc-name">${l.name}</div>
194      <div class="lc-disc">${l.disc}</div>
195      <div class="lc-disc">${l.need}</div>
196    </div>`).join('');
197}
198function pickRecharge(i){ rechargeSel=i; renderMember(); }
199function recharge(){ alert(`✅ 充值成功!\n\n到账 ¥${RECHARGE[rechargeSel].a},赠送 ${RECHARGE[rechargeSel].b}元\n余额:¥${(USER.balance+RECHARGE[rechargeSel].a).toFixed(1)}(演示页)`); }
200
201// 我的
202function renderMine(){
203  document.getElementById('p-name').textContent=USER.name;
204  document.getElementById('p-level').textContent=USER.level;
205  document.getElementById('p-points').textContent=USER.points;
206  document.getElementById('p-balance').textContent=USER.balance;
207  document.getElementById('p-coupons').textContent=USER.coupons;
208}
209