首页/ mobileweb/ 小草火锅/ 代码预览

💻 代码预览 · 小草火锅

mw_food · 上传者 小草网络
← 返回详情
小草火锅_H5/app.js · 约 9104 字符
1// 小草火锅 · 逻辑层
2const $=s=>document.querySelector(s), $$=s=>document.querySelectorAll(s);
3const store={
4  get cart(){return JSON.parse(localStorage.getItem('hp_cart')||'[]')},
5  set cart(v){localStorage.setItem('hp_cart',JSON.stringify(v))},
6  get orders(){return JSON.parse(localStorage.getItem('hp_orders')||'[]')},
7  set orders(v){localStorage.setItem('hp_orders',JSON.stringify(v))},
8  get coupons(){return JSON.parse(localStorage.getItem('hp_coupons')||JSON.stringify(COUPONS))},
9  set coupons(v){localStorage.setItem('hp_coupons',JSON.stringify(v))}
10};
11function fmt(n){return '¥'+n.toFixed(0)}
12function cartCount(){return store.cart.reduce((s,i)=>s+i.num,0)}
13function cartTotal(){return store.cart.reduce((s,i)=>s+i.num*i.price,0)}
14function toast(msg){const t=document.createElement('div');t.textContent=msg;t.style.cssText='position:fixed;top:20%;left:50%;transform:translateX(-50%);background:rgba(0,0,0,.78);color:#fff;padding:10px 20px;border-radius:20px;font-size:13px;z-index:999;transition:opacity .3s';document.body.appendChild(t);setTimeout(()=>{t.style.opacity='0';setTimeout(()=>t.remove(),300)},1200)}
15/* 点餐 */
16let curCat='meat', curPot=0, curSpicy='中辣';
17function addDish(id){
18  const d=DISHES.find(x=>x.id==id);if(!d)return;
19  const cart=store.cart;
20  const exist=cart.find(i=>i.id===id&&i.spicy===undefined);
21  if(exist)exist.num++;else cart.push({id,name:d.name,emoji:d.emoji,price:d.price,unit:d.unit,num:1});
22  store.cart=cart;toast('已加入 '+d.name);
23  refreshBar();
24}
25function renderMenu(){
26  $('#pot-list').innerHTML=POTS.map((p,i)=>`
27    <div class="pot-card">
28      <div class="pc-emoji">${p.emoji}</div>
29      <div class="pc-body">
30        <div class="pc-name">${p.name} ${p.tag==='hot'?'<span class="badge badge-hot">招牌</span>':p.tag==='new'?'<span class="badge badge-new">新品</span>':''}</div>
31        <div class="pc-desc">${p.desc}</div>
32        <div class="pc-foot"><span class="pc-price"><em>¥</em>${p.price}</span>
33        <span class="pc-add" style="width:26px;height:26px;border-radius:50%;background:linear-gradient(135deg,#d92626,#ff5a36);color:#fff;display:flex;align-items:center;justify-content:center;font-size:18px;cursor:pointer" onclick="curPot=${i};selectPot()">+</span></div>
34      </div>
35    </div>`).join('');
36  const list=DISHES.filter(d=>d.cat===curCat);
37  $('#dish-list').innerHTML='<h3 style="font-size:14px;color:#8a4a36;margin:8px 0">'+MENU_CATS.find(c=>c.id===curCat).name+'</h3>'+
38  list.map(d=>`
39    <div class="menu-item">
40      <div class="mi-img">${d.emoji}</div>
41      <div class="mi-body">
42        <div class="mi-name">${d.name} ${d.tag==='hot'?'<span class="badge badge-hot">必点</span>':d.tag==='new'?'<span class="badge badge-new">新品</span>':''}</div>
43        <div class="mi-desc">${d.desc}</div><div class="mi-spec">可备注半份/加量/少辣</div>
44        <div class="mi-foot"><span class="mi-price"><em>¥</em>${d.price}<small style="font-size:10px;color:#c08a78">/${d.unit}</small></span><span class="gc-add" style="width:26px;height:26px;border-radius:50%;background:linear-gradient(135deg,#d92626,#ff5a36);color:#fff;display:flex;align-items:center;justify-content:center;font-size:18px;cursor:pointer" onclick="addDish(${d.id})">+</span></div>
45      </div>
46    </div>`).join('');
47}
48function selectPot(){
49  const p=POTS[curPot];
50  let html='<div class="section-title" style="margin:0 0 8px">辣度选择 · '+p.name+'</div><div class="spicy-chips">';
51  p.spicy.forEach(s=>{html+='<span class="spicy-chip'+(s===curSpicy?' sel':'')+'" onclick="curSpicy=this.textContent;$$('.spicy-chip').forEach(x=>x.classList.remove('sel'));this.classList.add('sel');toast('锅底辣度:'+curSpicy)">'+s+'</span>'});
52  html+='</div><div style="font-size:11px;color:#c08a78;margin-top:10px">已选:'+p.name+'('+curSpicy+') · 锅底 ¥'+p.price+'</div>';
53  const sheet=document.createElement('div');
54  sheet.style.cssText='position:fixed;bottom:0;left:50%;transform:translateX(-50%);width:100%;max-width:430px;background:#fff;border-radius:16px 16px 0 0;z-index:201;padding:16px';
55  sheet.innerHTML=html+'<button class="btn btn-primary" style="margin-top:14px" onclick="confirmPot()">确认锅底</button>';
56  const mask=document.createElement('div');
57  mask.style.cssText='position:fixed;inset:0;background:rgba(0,0,0,.5);z-index:200';
58  mask.onclick=()=>{mask.remove();sheet.remove()};
59  document.body.appendChild(mask);document.body.appendChild(sheet);
60  window._sheet=[mask,sheet];
61}
62function confirmPot(){
63  const p=POTS[curPot];
64  const cart=store.cart;
65  const exist=cart.find(i=>i.id==='pot');
66  if(exist){exist.name='锅底·'+p.name;exist.price=p.price;exist.spicy=curSpicy}
67  else cart.unshift({id:'pot',name:'锅底·'+p.name,emoji:p.emoji,price:p.price,num:1,spicy:curSpicy});
68  store.cart=cart;toast('锅底已加入:'+p.name+'('+curSpicy+')');
69  window._sheet.forEach(el=>el.remove());
70  refreshBar();
71}
72function refreshBar(){
73  const c=cartCount();const bar=$('#cart-bar');
74  if(bar){bar.style.display=c?'flex':'none';
75  const el=$('#cb-count');if(el){el.textContent=c;el.style.display=c?'flex':'none'}
76  const t=$('#cb-total');if(t)t.textContent=fmt(cartTotal());}
77}
78function renderCartPage(){
79  const wrap=$('#cart-items');const cart=store.cart;
80  if(!cart.length){wrap.innerHTML='<div class="empty"><span class="e-icon">🍲</span>还没点菜<br>先选个锅底吧~</div>';$('#cart-submit').style.display='none';return}
81  $('#cart-submit').style.display='block';
82  wrap.innerHTML=cart.map((i,idx)=>`
83    <div class="order-item">
84      <div class="oi-img">${i.emoji}</div>
85      <div class="oi-body">
86        <div class="oi-name">${i.name}</div>
87        <div class="oi-spec">${i.spicy?'辣度 '+i.spicy:'可备注半份/少辣'}${i.unit?' · '+i.unit:''}</div>
88        <div class="oi-foot"><span class="oi-price">${fmt(i.price*i.num)}</span>
89          <span style="display:flex;align-items:center;gap:10px">
90            <span style="width:24px;height:24px;border-radius:50%;background:#fbe3d8;display:flex;align-items:center;justify-content:center;font-size:14px;cursor:pointer" onclick="chgQty(${idx},-1)">−</span>
91            <b style="font-size:14px">${i.num}</b>
92            <span style="width:24px;height:24px;border-radius:50%;background:#fbe3d8;display:flex;align-items:center;justify-content:center;font-size:14px;cursor:pointer" onclick="chgQty(${idx},1)">+</span>
93          </span>
94        </div>
95      </div>
96    </div>`).join('');
97  $('#cart-total').textContent=fmt(cartTotal());
98  $('#cart-count').textContent=cartCount();
99}
100function chgQty(idx,d){
101  const cart=store.cart;cart[idx].num+=d;
102  if(cart[idx].num<=0)cart.splice(idx,1);
103  store.cart=cart;renderCartPage();
104}
105function submitOrder(){
106  const cart=store.cart;
107  if(!cart.length){toast('请先点菜');return}
108  if(!cart.find(i=>i.id==='pot')){toast('先选个锅底吧');return}
109  const coupon=store.coupons.length?30:0;
110  const total=Math.max(0,cartTotal()-coupon);
111  const o={id:'HP'+Date.now().toString().slice(-8),items:cart.map(i=>({name:i.name,emoji:i.emoji,num:i.num,price:i.price,spicy:i.spicy})),total,time:new Date().toLocaleString('zh-CN',{hour:'2-digit',minute:'2-digit'}),status:0,table:'A12',code:'取餐码 36'+Math.floor(100+Math.random()*900)};
112  store.orders=[o,...store.orders];store.cart=[];store.coupons=store.coupons.slice(1);
113  toast('下单成功,锅底优先出餐');
114  setTimeout(()=>location.href='orders.html',800);
115}
116function renderOrdersPage(){
117  const wrap=$('#order-list');const orders=store.orders;
118  const steps=[['已下单','✓'],['锅底出锅','🍲'],['涮品出餐','🥩'],['开吃啦','😋']];
119  if(!orders.length){wrap.innerHTML='<div class="empty"><span class="e-icon">🍲</span>还没有订单<br>来一顿热腾腾的火锅吧~</div>';return}
120  wrap.innerHTML=orders.map(o=>`
121    <div class="order-card">
122      <div class="oc-head"><span>${o.time} · 桌号 ${o.table}</span><span class="oc-status">● ${['已下单','备餐中','配送中','已完成'][o.status]}</span></div>
123      <div class="oc-body"><span class="oc-emoji">🍲</span>
124        <div><div class="oc-name">${o.items[0].name}${o.items.length>1?' 等'+o.items.length+'项':''}</div><div class="oc-meta">${o.items.map(i=>i.emoji+i.num).join(' ')}</div></div>
125        <div class="oc-price">¥${o.total}</div>
126      </div>
127      <div class="oc-steps">${steps.map((s,i)=>'<div class="os '+(i<o.status?'done':i===o.status?'now':'')+'"><span class="dot">'+s[1]+'</span>'+s[0]+'</div>').join('')}</div>
128      <div style="font-size:11px;color:#c08a78;margin-top:8px">💡 ${o.code} · 到店报码开吃,蘸料台自助取用</div>
129    </div>`).join('');
130}
131function renderMine(){
132  $('#u-name').textContent=USER.name;$('#u-level').textContent=USER.level;
133  $('#m-points').textContent=USER.points;$('#m-balance').textContent=USER.balance;
134  $('#m-coupons').textContent=USER.coupons+store.coupons.length;
135  $('#m-times').textContent=USER.times;
136}
137