目標
把 review.html 的心得列表做成對話框風格、加陰影與分隔;長列表用「載入更多」。
改哪裡:style.css、js/reviews.js
style.css 末尾)/* Day 13:心得對話框風格 + 分隔 */
.review-item{
position: relative;
background: var(--surface);
border: 1px solid var(--border);
border-radius: 18px;
padding: 14px 16px;
box-shadow: var(--shadow-sm);
}
.review-item::before{
content: "";
position: absolute;
left: 20px; top: -8px;
border: 8px solid transparent;
border-bottom-color: var(--border);
}
.review-item::after{
content: "";
position: absolute;
left: 20px; top: -7px;
border: 7px solid transparent;
border-bottom-color: var(--surface);
}
.reviews.separated > .review-item + .review-item{ margin-top: 10px; }
.loadmore-wrap{ display:flex; justify-content:center; margin-top: 10px; }
#btnLoadMore{ padding:10px 14px; border-radius:10px; border:1px solid var(--border); background:var(--surface); cursor:pointer; }
#btnLoadMore:hover{ border-color: var(--text); }
js/reviews.js 的 render 相關部分即可)在 Day12 版中,加入「分頁顯示」,保留 LocalStorage:
// 只貼需新增/替換的片段 —— 放在 Day12 版 reviews.js 內
// 額外狀態:每次顯示幾筆
let PAGE_SIZE = 5;
let visibleCount = PAGE_SIZE;
function mountLoadMore(){
const total = REVIEWS.length;
const $wrap = $('.loadmore-wrap');
if ($wrap.length === 0){
$('#reviewList').after('<div class="loadmore-wrap"><button id="btnLoadMore" type="button">載入更多</button></div>');
}
if (visibleCount >= total) {
$('#btnLoadMore').prop('disabled', true).text('沒有更多了');
} else {
$('#btnLoadMore').prop('disabled', false).text('載入更多');
}
}
function render(){
if (!REVIEWS.length){
$('#reviewList').html(`<div class="empty">目前還沒有心得,快成為第一個分享的人吧!</div>`);
$('.loadmore-wrap').remove();
return;
}
const sorted = REVIEWS.slice().sort((a,b) => (b.createdAt || '').localeCompare(a.createdAt || ''));
const cut = sorted.slice(0, visibleCount);
const html = cut.map(item => {
const tags = (item.genres || []).map(g => LABELS[g] || g).join(' / ');
const dateStr = (item.createdAt || '').slice(0,10);
return `
<article class="review-item" data-id="${item.id}">
<div class="review-head">
<h3 class="review-title">${esc(item.title)}</h3>
<span class="review-meta">⭐ ${item.rating} · ${esc(item.name || '匿名')}${tags?` · ${tags}`:''}${dateStr?` · ${dateStr}`:''}</span>
</div>
<p class="review-content">${esc(item.content)}</p>
<div class="review-actions">
<button class="btn-del" type="button">刪除</button>
</div>
</article>
`;
}).join('');
$('#reviewList').toggleClass('separated', true).html(html);
mountLoadMore();
}
$(document).on('click', '#btnLoadMore', function(){
visibleCount += PAGE_SIZE;
render();
});
// 初始化時確保第一頁
$(function(){
visibleCount = PAGE_SIZE;
render();
});
驗收