app.js · 约 7576 字符
1// 小草酒店民宿 · 交互逻辑
2function $(id){return document.getElementById(id)}
3const hotelCard = h => `
4 <a class="hotel-card" href="detail.html?id=${h.id}">
5 <div class="hc-img">${h.icon}</div>
6 <div class="hc-info">
7 <div class="hc-name">${h.name}</div>
8 <div class="hc-loc">📍 ${h.loc}</div>
9 <div class="hc-tags">${h.tags.map(t=>`<span class="tag">${t}</span>`).join('')}</div>
10 <div class="hc-bottom">
11 <div class="hc-price">¥${h.price} <small>/晚起</small></div>
12 <div class="hc-score"><b>${h.score}</b> 分</div>
13 </div>
14 </div>
15 </a>`;
16
17// 首页
18function renderIndex(){
19 const cs = $('cat-scroll');
20 cs.innerHTML = CATS.map((c,i)=>`<a href="hotels.html" class="${i===0?'active':''}"><span class="ci">${c.icon}</span>${c.name}</a>`).join('');
21 $('hotel-list').innerHTML = HOTELS.slice(0,4).map(hotelCard).join('');
22 $('rev-preview').innerHTML = REVIEWS.slice(0,2).map(r=>`
23 <div style="display:flex;gap:10px;padding:8px 0">
24 <div style="width:36px;height:36px;border-radius:50%;background:var(--primary-light);display:flex;align-items:center;justify-content:center;font-size:18px;flex-shrink:0">${r.av}</div>
25 <div><div style="font-size:13px;font-weight:600">${r.name} <span style="color:#d48806;font-size:12px">${r.score}分</span></div>
26 <div style="font-size:12px;color:#666;margin-top:3px">${r.text}</div></div>
27 </div>`).join('');
28}
29
30// 列表
31let hotelFilter = '全部';
32function renderHotelList(){
33 const fb = $('filter-bar');
34 fb.innerHTML = ['全部','民宿','酒店','别墅','公寓','温泉','5.0分以上','¥500以内'].map(f=>
35 `<a class="${f===hotelFilter?'active':''}" onclick="setFilter('${f}')">${f}</a>`).join('');
36 renderHotels();
37}
38function setFilter(f){ hotelFilter=f; renderHotels(); }
39function renderHotels(){
40 let list = HOTELS;
41 if(hotelFilter==='5.0分以上') list = list.filter(h=>h.score>=5.0);
42 else if(hotelFilter==='¥500以内') list = list.filter(h=>h.price<=500);
43 else if(hotelFilter!=='全部') list = list.filter(h=>h.cat===hotelFilter);
44 $('hotel-list').innerHTML = list.length ? list.map(hotelCard).join('') :
45 '<div class="empty"><div class="eicon">🏨</div><div>没有符合条件的房源</div></div>';
46}
47
48// 详情
49let curHotel = HOTELS[0];
50function renderDetail(){
51 const id = new URLSearchParams(location.search).get('id')||1;
52 curHotel = HOTELS.find(h=>h.id==id) || HOTELS[0];
53 $('hero-icon').textContent = curHotel.icon;
54 $('d-name').textContent = curHotel.name;
55 $('d-loc').textContent = '📍 ' + curHotel.loc;
56 $('d-price').textContent = curHotel.price;
57 $('d-score').textContent = curHotel.score;
58 $('d-reviews').textContent = curHotel.reviews;
59 $('fac-grid').innerHTML = FACILITIES.map(f=>`<div class="fac-item"><span class="fi">${f.icon}</span>${f.name}</div>`).join('');
60 // 房态日历(生成当月)
61 renderCalendar();
62 $('rev-list').innerHTML = REVIEWS.map(r=>`
63 <div class="review-item">
64 <div class="rv-av">${r.av}</div>
65 <div class="rv-info"><div class="rv-name">${r.name}<span>⭐ ${r.score}</span></div><div class="rv-text">${r.text}</div></div>
66 </div>`).join('');
67}
68function renderCalendar(){
69 const el = $('calendar'); if(!el) return;
70 const now = new Date();
71 const year = now.getFullYear(), month = now.getMonth();
72 const first = new Date(year, month, 1).getDay();
73 const days = new Date(year, month+1, 0).getDate();
74 let html = '<div class="calendar">';
75 ['日','一','二','三','四','五','六'].forEach(d=>html+=`<div class="cal-head">${d}</div>`);
76 for(let i=0;i<first;i++) html+='<div></div>';
77 const today = now.getDate();
78 for(let d=1;d<=days;d++){
79 let cls='cal-day';
80 if(d<today) cls+=' past';
81 else if(d>=today+3 && d<today+6) cls+=' full';
82 else if(d>=today && d<today+3) cls+=' avail';
83 if(d===today+1) cls+=' sel';
84 html+=`<div class="${cls}">${d}</div>`;
85 }
86 html+='</div><div style="font-size:11px;color:#999;margin-top:8px">🟨 可订 ⬜ 已满 淡季价¥'+curHotel.price+' / 周末+50</div>';
87 el.innerHTML = html;
88}
89function favHotel(){ alert('❤️ 已收藏「'+curHotel.name+'」'); }
90
91// 预订
92let curCoupon = 0;
93function renderBook(){
94 $('b-icon').textContent = curHotel.icon;
95 $('b-name').textContent = curHotel.name;
96 $('b-price').textContent = '¥' + curHotel.price;
97 $('s-price').textContent = curHotel.price;
98 calcTotal();
99 $('coupon-list').innerHTML = COUPONS.map((c,i)=>`
100 <div class="coupon-item" onclick="pickCoupon(${i})" style="${i===curCoupon?'border:2px solid var(--primary)':''}">
101 <div class="c-left"><div class="c-amount">¥${c.amount}</div><div class="c-label">优惠券</div></div>
102 <div class="c-right"><div class="c-name">${c.name} ${i===curCoupon?'✓':''}</div><div class="c-desc">${c.desc} · ${c.expire}到期</div></div>
103 </div>`).join('');
104}
105function pickCoupon(i){ curCoupon=i; renderBook(); }
106function calcTotal(){
107 const sub = curHotel.price;
108 const coupon = COUPONS[curCoupon] ? COUPONS[curCoupon].amount : 0;
109 const total = sub + 20 - coupon;
110 $('s-sub').textContent = '¥' + sub;
111 $('s-coupon').textContent = '-¥' + coupon;
112 $('s-total').textContent = '¥' + total;
113}
114function doBook(){
115 const name = $('b-name-input').value.trim();
116 const phone = $('b-phone').value.trim();
117 if(!name){ alert('请填写入住人姓名'); return; }
118 if(!/^1\d{10}$/.test(phone)){ alert('请输入正确的手机号'); return; }
119 alert('✅ 预订成功!\n订单已生成,确认短信已发送\n到店报姓名即可办理入住');
120}
121
122// 订单
123let orderFilter = '';
124function renderOrders(){
125 const list = $('order-list');
126 let orders = ORDERS;
127 if(orderFilter) orders = orders.filter(o=>o.status===orderFilter);
128 if(!orders.length){ list.innerHTML='<div class="empty"><div class="eicon">📋</div><div>暂无订单</div></div>'; return; }
129 list.innerHTML = orders.map(o=>`
130 <div class="order-item">
131 <div class="oi-top"><span style="font-size:13px;color:#999">${o.id}</span>
132 <span class="oi-status" style="color:${o.status==='已完成'?'var(--green)':o.status==='已取消'?'#999':'var(--primary)'}">${o.status}</span></div>
133 <div class="oi-hotel">
134 <div class="oh-img">${o.icon}</div>
135 <div class="oh-info"><b>${o.hotel}</b><span>${o.type} · ${o.date}</span></div>
136 </div>
137 <div class="oi-bottom"><span style="font-size:12px;color:#999">${o.status==='待入住'?'查看入住凭证':'订单详情'}</span><span class="oi-total">${o.total?'¥'+o.total:'--'}</span></div>
138 </div>`).join('');
139}
140function filterOrder(el, f){ orderFilter=f;
141 document.querySelectorAll('.filter-bar a').forEach(a=>a.classList.remove('active'));
142 el.classList.add('active'); renderOrders();
143}
144
145// 我的
146function renderMine(){
147 $('m-name').textContent = MEMBER.name;
148 $('m-level').textContent = MEMBER.level;
149 $('m-points').textContent = MEMBER.points;
150 $('m-coupons').textContent = MEMBER.coupons;
151 $('m-orders').textContent = MEMBER.orders;
152 $('m-favs').textContent = MEMBER.favs + ' 个 ›';
153 $('m-coupon-list').innerHTML = COUPONS.map(c=>`
154 <div class="coupon-item">
155 <div class="c-left"><div class="c-amount">¥${c.amount}</div><div class="c-label">优惠券</div></div>
156 <div class="c-right"><div class="c-name">${c.name}</div><div class="c-desc">${c.desc} · ${c.expire}到期</div></div>
157 </div>`).join('');
158}
159