小草景区门票_H5/app.js · 约 5063 字符
1// 小草景区门票 · 逻辑层
2const $=s=>document.querySelector(s), $$=s=>document.querySelectorAll(s);
3const store={
4 get orders(){return JSON.parse(localStorage.getItem('sc_orders')||'[]')},
5 set orders(v){localStorage.setItem('sc_orders',JSON.stringify(v))},
6 get coupons(){return JSON.parse(localStorage.getItem('sc_coupons')||'3')},
7 set coupons(v){localStorage.setItem('sc_coupons',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={ticket:null,date:0,qty:1};
13function renderDetail(){
14 const id=new URLSearchParams(location.search).get('id')||1;
15 const s=SPOTS.find(x=>x.id==id);window.CURRENT=s;
16 $('#d-hero').textContent=s.emoji;$('#d-name').textContent=s.name;
17 $('#d-meta').innerHTML='<span>📍 '+s.city+'</span><span>⭐ '+s.score+'</span><span>'+s.tags.join(' · ')+'</span>';
18 $('#d-desc').textContent=s.desc;
19 $('#ticket-list').innerHTML=TICKETS.map((t,i)=>`
20 <div class="ticket-type" onclick="BK.ticket=${i};$$('.ticket-type').forEach(x=>x.classList.remove('sel'));this.classList.add('sel')">
21 <div style="flex:1"><div class="tt-name">${t.name}</div><div class="tt-meta">${t.meta}</div></div>
22 <span class="tt-price"><em>¥</em>${t.price}</span>
23 </div>`).join('');
24 $('#date-tabs').innerHTML=DATES.map((d,i)=>'<div class="date-tab'+(i===0?' sel':'')+'" onclick="BK.date='+i+';$$('.date-tab').forEach(x=>x.classList.remove('sel'));this.classList.add('sel')">'+d+'<br><small style="color:#8aa896;font-size:10px">'+(i===0?'余票充足':'余票'+[286,120,45][i%3]+'张')+'</small></div>').join('');
25}
26function submitBuy(){
27 if(BK.ticket===null){toast('请选择票种');return}
28 const s=CURRENT;const t=TICKETS[BK.ticket];
29 const o={id:'SC'+Date.now().toString().slice(-8),spot:s.name,emoji:s.emoji,ticket:t.name,price:t.price,qty:BK.qty,date:DATES[BK.date],total:t.price*BK.qty,time:new Date().toLocaleString('zh-CN',{month:'numeric',day:'numeric'}),status:'待使用',code:'E'+Math.floor(100000+Math.random()*900000)};
30 store.orders=[o,...store.orders];store.coupons=Math.max(0,store.coupons-1);
31 toast('购票成功,电子票已生成');
32 setTimeout(()=>location.href='orders.html',800);
33}
34function renderOrders(){
35 const wrap=$('#order-list');const orders=store.orders;
36 if(!orders.length){wrap.innerHTML='<div class="empty"><span class="e-icon">🎫</span>还没有订单<br>去挑个景区出发吧~</div>';return}
37 wrap.innerHTML=orders.map(o=>`
38 <div class="order-card">
39 <div class="oc-head"><span>${o.time} · 订单号 ${o.id}</span><span class="oc-status">● ${o.status}</span></div>
40 <div class="oc-body"><span class="oc-emoji">${o.emoji}</span>
41 <div><div class="oc-name">${o.spot} · ${o.ticket}</div><div class="oc-meta">${o.date} · ${o.qty}张 · 分时预约入园</div></div>
42 <div class="oc-price">¥${o.total}</div>
43 </div>
44 <div style="display:flex;gap:8px;margin-top:12px">
45 <button class="btn btn-outline" style="flex:1;padding:9px;font-size:13px" onclick="toast('退票申请已提交,1-2个工作日原路退回')">申请退票</button>
46 <button class="btn btn-primary" style="flex:1;padding:9px;font-size:13px" onclick="location.href='tickets.html'">查看电子票</button>
47 </div>
48 </div>`).join('');
49}
50function renderTickets(){
51 const list=store.orders.length?store.orders.map(o=>({emoji:o.emoji,name:o.spot+' · '+o.ticket,meta:o.date+' · '+o.qty+'张',status:o.status,code:o.code})):TICKET_LIST;
52 $('#ticket-items').innerHTML=list.slice(0,3).map(t=>`
53 <div class="ticket-item">
54 <span class="ti-emoji">${t.emoji}</span>
55 <div class="ti-body"><div class="ti-name">${t.name}</div><div class="ti-meta">${t.meta}</div></div>
56 <span class="ti-status${t.status==='已使用'?'':t.status==='待使用'?'':' warn'}">${t.status==='待使用'?'待使用':t.status==='已使用'?'已使用':'待使用'}</span>
57 </div>`).join('');
58 $('#qr-list').innerHTML=list.slice(0,2).map(t=>`
59 <div class="qr-box">
60 <div style="font-size:14px;font-weight:700">${t.name}</div>
61 <div class="qb-qr">🎫</div>
62 <div class="qb-code">${t.code||('E'+Math.floor(100000+Math.random()*900000))}</div>
63 <div class="qb-tip">凭此码/身份证/人脸识别入园 · 一码一票</div>
64 </div>`).join('');
65}
66function renderMine(){
67 $('#u-name').textContent=USER.name;$('#u-level').textContent=USER.level+' · 已游 '+USER.orders+' 个景区';
68 $('#m-points').textContent=USER.points;$('#m-orders').textContent=USER.orders;
69 $('#m-coupons').textContent=USER.coupons+store.coupons;
70 $('#m-stars').textContent='4.8';
71}
72