小草美甲美妆_H5/app.js · 约 4358 字符
1// 小草美甲美妆 · 逻辑层
2const $=s=>document.querySelector(s), $$=s=>document.querySelectorAll(s);
3const store={
4 get orders(){return JSON.parse(localStorage.getItem('nl_orders')||'[]')},
5 set orders(v){localStorage.setItem('nl_orders',JSON.stringify(v))},
6 get coupons(){return JSON.parse(localStorage.getItem('nl_coupons')||JSON.stringify(COUPONS))},
7 set coupons(v){localStorage.setItem('nl_coupons',JSON.stringify(v))}
8};
9function fmt(n){return '¥'+n.toFixed(0)}
10function 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)}
11/* 预约 */
12let BK={svc:null,time:null,nailer:null};
13function renderSvc(){
14 $('#svc-list').innerHTML=SERVICES.map((s,i)=>`
15 <div class="service-card">
16 <div class="sc-emoji">${s.emoji}</div>
17 <div class="sc-body">
18 <div class="sc-name">${s.name} ${s.tag==='hot'?'<span class="badge badge-hot">热门</span>':s.tag==='new'?'<span class="badge badge-new">上新</span>':''}</div>
19 <div class="sc-desc">${s.desc}</div>
20 <div class="sc-meta">⏱️ ${s.time} · ${CATS.find(c=>c.id===s.cat).name}</div>
21 <div class="sc-foot"><span class="sc-price"><em>¥</em>${s.price}</span>
22 <span class="sc-add" onclick="BK.svc=${i};$$('.sc-add').forEach(x=>{x.style.background='var(--primary-light)';x.style.color='var(--primary-dark)';x.textContent='预约'});this.style.background='var(--primary)';this.style.color='#fff';this.textContent='已选';toast('已选择「${s.name}」')">预约</span></div>
23 </div>
24 </div>`).join('');
25}
26function renderTimes(){
27 $('#time-grid').innerHTML=TIMES.map(t=>{
28 const full=FULL_TIMES.includes(t);
29 return '<div class="time-cell'+(full?' full':'')+'" onclick="'+(full?"toast('该时段已约满,试试其他时段')":"BK.time='"+t+"';$$('.time-cell').forEach(x=>x.classList.remove('sel'));this.classList.add('sel')")+'">'+t+'</div>';
30 }).join('');
31}
32function submitBook(){
33 if(BK.svc===null){toast('请先选择服务项目');return}
34 if(!BK.time){toast('请选择到店时段');return}
35 const svc=SERVICES[BK.svc];
36 const deposit=Math.round(svc.price*0.3);
37 const o={id:'NL'+Date.now().toString().slice(-8),service:svc.name,emoji:svc.emoji,time:BK.time+' · 明天',price:svc.price,deposit,store:'小草美甲(总店)',status:'待确认',step:0,date:new Date().toLocaleString('zh-CN',{month:'numeric',day:'numeric'})};
38 store.orders=[o,...store.orders];
39 store.coupons=store.coupons.slice(1);
40 toast('预约成功,定金 '+fmt(deposit)+' 元');
41 setTimeout(()=>location.href='orders.html',800);
42}
43function renderOrdersPage(){
44 const wrap=$('#order-list');const orders=store.orders;
45 const steps=[['待确认','✓'],['已确认','✓'],['服务中','💅'],['已完成','🎉']];
46 if(!orders.length){wrap.innerHTML='<div class="empty"><span class="e-icon">💅</span>还没有预约<br>来做一款美美的指甲吧~</div>';return}
47 wrap.innerHTML=orders.map(o=>`
48 <div class="order-card">
49 <div class="oc-head"><span>${o.date} · 预约号 ${o.id}</span><span class="oc-status">● ${o.status}</span></div>
50 <div class="oc-body"><span class="oc-emoji">${o.emoji}</span>
51 <div><div class="oc-name">${o.service}</div><div class="oc-meta">${o.store} · ${o.time} · 技师 Lisa</div></div>
52 <div class="oc-price">¥${o.price}</div>
53 </div>
54 <div class="oc-steps">
55 ${steps.map((s,i)=>'<div class="os '+(i<o.step?'done':i===o.step?'now':'')+'"><span class="dot">'+s[1]+'</span>'+s[0]+'</div>').join('')}
56 </div>
57 <div style="font-size:11px;color:#a893b8;margin-top:8px">💡 已付定金 ¥${o.deposit},服务完成后支付尾款 · 爽约不退</div>
58 </div>`).join('');
59}
60function renderMine(){
61 $('#u-name').textContent=USER.name;$('#u-level').textContent=USER.level;
62 $('#m-points').textContent=USER.points;$('#m-balance').textContent=USER.balance;
63 $('#m-coupons').textContent=USER.coupons+store.coupons.length;
64 $('#m-times').textContent=USER.times;
65}
66