447 lines
17 KiB
JavaScript
447 lines
17 KiB
JavaScript
// 送花服务功能管理类
|
||
class FlowerManager {
|
||
constructor() {
|
||
this.flowers = [];
|
||
this.filteredFlowers = [];
|
||
this.currentFilters = {
|
||
category: '',
|
||
price: '',
|
||
occasion: ''
|
||
};
|
||
this.init();
|
||
}
|
||
|
||
// 初始化方法
|
||
init() {
|
||
this.loadFlowers();
|
||
this.bindEvents();
|
||
AOS.init({
|
||
duration: 1000,
|
||
once: true
|
||
});
|
||
}
|
||
|
||
// 绑定事件
|
||
bindEvents() {
|
||
// 筛选器变化事件
|
||
document.getElementById('filter-category').addEventListener('change', (e) => {
|
||
this.currentFilters.category = e.target.value;
|
||
});
|
||
|
||
document.getElementById('filter-price').addEventListener('change', (e) => {
|
||
this.currentFilters.price = e.target.value;
|
||
});
|
||
|
||
document.getElementById('filter-occasion').addEventListener('change', (e) => {
|
||
this.currentFilters.occasion = e.target.value;
|
||
});
|
||
|
||
// 筛选按钮点击事件
|
||
document.querySelector('.flower-filter button').addEventListener('click', () => {
|
||
this.filterFlowers();
|
||
});
|
||
|
||
// 页面加载完成后显示鲜花
|
||
document.addEventListener('DOMContentLoaded', () => {
|
||
this.displayFlowers();
|
||
});
|
||
}
|
||
|
||
// 加载鲜花数据(模拟数据)
|
||
loadFlowers() {
|
||
this.flowers = [
|
||
{
|
||
id: 1,
|
||
name: '浪漫红玫瑰',
|
||
description: '99朵红玫瑰,象征永恒的爱情和浪漫',
|
||
price: 299,
|
||
originalPrice: 399,
|
||
image: 'images/flower-rose.svg',
|
||
category: 'love',
|
||
occasion: 'valentine',
|
||
tags: ['love', 'romantic'],
|
||
inStock: true,
|
||
rating: 4.8
|
||
},
|
||
{
|
||
id: 2,
|
||
name: '生日祝福花束',
|
||
description: '多彩花束,包含康乃馨、百合和满天星',
|
||
price: 199,
|
||
originalPrice: 259,
|
||
image: 'images/flower-birthday.svg',
|
||
category: 'birthday',
|
||
occasion: 'birthday',
|
||
tags: ['birthday', 'celebration'],
|
||
inStock: true,
|
||
rating: 4.6
|
||
},
|
||
{
|
||
id: 3,
|
||
name: '商务庆典花篮',
|
||
description: '大型花篮,适合开业、庆典等商务场合',
|
||
price: 599,
|
||
originalPrice: 699,
|
||
image: 'images/flower-business.svg',
|
||
category: 'celebration',
|
||
occasion: 'anniversary',
|
||
tags: ['business', 'celebration'],
|
||
inStock: true,
|
||
rating: 4.7
|
||
},
|
||
{
|
||
id: 4,
|
||
name: '温馨慰问花束',
|
||
description: '淡雅花束,表达关怀和慰问之情',
|
||
price: 159,
|
||
originalPrice: 199,
|
||
image: 'images/flower-sympathy.svg',
|
||
category: 'sympathy',
|
||
occasion: 'thanks',
|
||
tags: ['sympathy', 'care'],
|
||
inStock: true,
|
||
rating: 4.5
|
||
},
|
||
{
|
||
id: 5,
|
||
name: '永恒爱意花盒',
|
||
description: '精美礼盒装,包含玫瑰和配花,永久保存',
|
||
price: 459,
|
||
originalPrice: 599,
|
||
image: 'images/flower-box.svg',
|
||
category: 'love',
|
||
occasion: 'anniversary',
|
||
tags: ['love', 'premium'],
|
||
inStock: true,
|
||
rating: 4.9
|
||
},
|
||
{
|
||
id: 6,
|
||
name: '感恩花束',
|
||
description: '向日葵为主的花束,表达感谢和敬意',
|
||
price: 229,
|
||
originalPrice: 279,
|
||
image: 'images/flower-thanks.svg',
|
||
category: 'celebration',
|
||
occasion: 'thanks',
|
||
tags: ['thanks', 'gratitude'],
|
||
inStock: true,
|
||
rating: 4.4
|
||
}
|
||
];
|
||
this.filteredFlowers = [...this.flowers];
|
||
}
|
||
|
||
// 筛选鲜花
|
||
filterFlowers() {
|
||
this.filteredFlowers = this.flowers.filter(flower => {
|
||
let match = true;
|
||
|
||
// 分类筛选
|
||
if (this.currentFilters.category && flower.category !== this.currentFilters.category) {
|
||
match = false;
|
||
}
|
||
|
||
// 价格筛选
|
||
if (this.currentFilters.price) {
|
||
const [min, max] = this.currentFilters.price.split('-');
|
||
if (max === '+') {
|
||
if (flower.price < parseInt(min)) {
|
||
match = false;
|
||
}
|
||
} else {
|
||
if (flower.price < parseInt(min) || flower.price > parseInt(max)) {
|
||
match = false;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 场合筛选
|
||
if (this.currentFilters.occasion && flower.occasion !== this.currentFilters.occasion) {
|
||
match = false;
|
||
}
|
||
|
||
return match;
|
||
});
|
||
|
||
this.displayFlowers();
|
||
}
|
||
|
||
// 显示鲜花列表
|
||
displayFlowers() {
|
||
const container = document.getElementById('flowers-container');
|
||
|
||
if (this.filteredFlowers.length === 0) {
|
||
container.innerHTML = `
|
||
<div class="col-12">
|
||
<div class="flower-empty">
|
||
<i class="fa fa-search"></i>
|
||
<h4>没有找到符合条件的鲜花</h4>
|
||
<p>请尝试调整筛选条件</p>
|
||
</div>
|
||
</div>
|
||
`;
|
||
return;
|
||
}
|
||
|
||
container.innerHTML = this.filteredFlowers.map(flower => `
|
||
<div class="col-md-4 mb-4" data-aos="fade-up">
|
||
<div class="card flower-card h-100">
|
||
${flower.originalPrice > flower.price ?
|
||
`<span class="discount-badge">-${Math.round((1 - flower.price / flower.originalPrice) * 100)}%</span>` :
|
||
''
|
||
}
|
||
<img src="${flower.image}" class="card-img-top" alt="${flower.name}"
|
||
onerror="this.src='images/flower-placeholder.svg'">
|
||
<div class="card-body">
|
||
<div class="flower-tags">
|
||
${flower.tags.map(tag => `<span class="flower-tag ${tag}">${this.getTagName(tag)}</span>`).join('')}
|
||
</div>
|
||
<h5 class="card-title">${flower.name}</h5>
|
||
<p class="card-text text-muted">${flower.description}</p>
|
||
<div class="d-flex justify-content-between align-items-center mb-3">
|
||
<div>
|
||
<span class="flower-price">¥${flower.price}</span>
|
||
${flower.originalPrice > flower.price ?
|
||
`<span class="flower-original-price ms-2">¥${flower.originalPrice}</span>` :
|
||
''
|
||
}
|
||
</div>
|
||
<div class="text-warning">
|
||
<i class="fa fa-star"></i>
|
||
<span>${flower.rating}</span>
|
||
</div>
|
||
</div>
|
||
<div class="d-grid">
|
||
<button class="btn btn-flower" onclick="flowerManager.showOrderForm(${flower.id})">
|
||
立即订购
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
`).join('');
|
||
}
|
||
|
||
// 获取标签名称
|
||
getTagName(tag) {
|
||
const tagNames = {
|
||
'love': '爱情',
|
||
'romantic': '浪漫',
|
||
'birthday': '生日',
|
||
'celebration': '庆典',
|
||
'business': '商务',
|
||
'sympathy': '慰问',
|
||
'care': '关怀',
|
||
'premium': '精品',
|
||
'thanks': '感谢',
|
||
'gratitude': '感恩'
|
||
};
|
||
return tagNames[tag] || tag;
|
||
}
|
||
|
||
// 显示订购表单
|
||
showOrderForm(flowerId) {
|
||
const flower = this.flowers.find(f => f.id === flowerId);
|
||
if (!flower) return;
|
||
|
||
// 创建模态框
|
||
const modalHtml = `
|
||
<div class="modal fade" id="orderModal" tabindex="-1">
|
||
<div class="modal-dialog modal-lg">
|
||
<div class="modal-content">
|
||
<div class="modal-header">
|
||
<h5 class="modal-title">订购 ${flower.name}</h5>
|
||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||
</div>
|
||
<div class="modal-body">
|
||
<div class="row">
|
||
<div class="col-md-6">
|
||
<img src="${flower.image}" class="img-fluid rounded" alt="${flower.name}"
|
||
onerror="this.src='images/flower-placeholder.svg'">
|
||
<div class="mt-3">
|
||
<h4>${flower.name}</h4>
|
||
<p class="text-muted">${flower.description}</p>
|
||
<div class="d-flex justify-content-between align-items-center">
|
||
<span class="flower-price">¥${flower.price}</span>
|
||
<span class="badge bg-success">有货</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="col-md-6">
|
||
<form id="orderForm">
|
||
<div class="mb-3">
|
||
<label class="form-label">收花人姓名</label>
|
||
<input type="text" class="form-control" name="recipientName" required>
|
||
</div>
|
||
<div class="mb-3">
|
||
<label class="form-label">收花人电话</label>
|
||
<input type="tel" class="form-control" name="recipientPhone" required>
|
||
</div>
|
||
<div class="mb-3">
|
||
<label class="form-label">配送地址</label>
|
||
<textarea class="form-control" name="deliveryAddress" rows="3" required></textarea>
|
||
</div>
|
||
<div class="mb-3">
|
||
<label class="form-label">配送时间</label>
|
||
<input type="datetime-local" class="form-control" name="deliveryTime" required>
|
||
</div>
|
||
<div class="mb-3">
|
||
<label class="form-label">祝福语</label>
|
||
<textarea class="form-control" name="greeting" rows="2"
|
||
placeholder="写下你的祝福..."></textarea>
|
||
</div>
|
||
<div class="mb-3">
|
||
<label class="form-label">支付方式</label>
|
||
<select class="form-select" name="paymentMethod" required>
|
||
<option value="">请选择支付方式</option>
|
||
<option value="wechat">微信支付</option>
|
||
<option value="alipay">支付宝</option>
|
||
<option value="bank">银行转账</option>
|
||
</select>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="modal-footer">
|
||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
|
||
<button type="button" class="btn btn-flower" onclick="flowerManager.submitOrder(${flower.id})">
|
||
确认订购 (¥${flower.price})
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
`;
|
||
|
||
// 添加模态框到页面
|
||
if (!document.getElementById('orderModal')) {
|
||
document.body.insertAdjacentHTML('beforeend', modalHtml);
|
||
}
|
||
|
||
// 显示模态框
|
||
const modal = new bootstrap.Modal(document.getElementById('orderModal'));
|
||
modal.show();
|
||
}
|
||
|
||
// 提交订单
|
||
submitOrder(flowerId) {
|
||
const form = document.getElementById('orderForm');
|
||
if (!form.checkValidity()) {
|
||
form.reportValidity();
|
||
return;
|
||
}
|
||
|
||
const formData = new FormData(form);
|
||
const orderData = {
|
||
flowerId,
|
||
recipientName: formData.get('recipientName'),
|
||
recipientPhone: formData.get('recipientPhone'),
|
||
deliveryAddress: formData.get('deliveryAddress'),
|
||
deliveryTime: formData.get('deliveryTime'),
|
||
greeting: formData.get('greeting'),
|
||
paymentMethod: formData.get('paymentMethod'),
|
||
timestamp: new Date().toISOString()
|
||
};
|
||
|
||
// 模拟提交订单
|
||
this.showOrderSuccess(orderData);
|
||
}
|
||
|
||
// 显示订单成功
|
||
showOrderSuccess(orderData) {
|
||
// 关闭订购模态框
|
||
const modal = bootstrap.Modal.getInstance(document.getElementById('orderModal'));
|
||
modal.hide();
|
||
|
||
// 显示成功提示
|
||
Swal.fire({
|
||
icon: 'success',
|
||
title: '订购成功!',
|
||
html: `
|
||
<div class="text-start">
|
||
<p><strong>订单详情:</strong></p>
|
||
<p>收花人:${orderData.recipientName}</p>
|
||
<p>电话:${orderData.recipientPhone}</p>
|
||
<p>配送地址:${orderData.deliveryAddress}</p>
|
||
<p>配送时间:${new Date(orderData.deliveryTime).toLocaleString()}</p>
|
||
<p class="mt-3">我们会在配送前与您确认,感谢您的订购!</p>
|
||
</div>
|
||
`,
|
||
confirmButtonText: '确定',
|
||
confirmButtonColor: '#ff6b6b'
|
||
});
|
||
}
|
||
|
||
// 搜索鲜花
|
||
searchFlowers(query) {
|
||
if (!query.trim()) {
|
||
this.filteredFlowers = [...this.flowers];
|
||
} else {
|
||
this.filteredFlowers = this.flowers.filter(flower =>
|
||
flower.name.toLowerCase().includes(query.toLowerCase()) ||
|
||
flower.description.toLowerCase().includes(query.toLowerCase()) ||
|
||
flower.tags.some(tag => tag.toLowerCase().includes(query.toLowerCase()))
|
||
);
|
||
}
|
||
this.displayFlowers();
|
||
}
|
||
}
|
||
|
||
// 页面加载完成后初始化
|
||
let flowerManager;
|
||
document.addEventListener('DOMContentLoaded', function() {
|
||
flowerManager = new FlowerManager();
|
||
|
||
// 添加搜索功能(如果需要)
|
||
const searchInput = document.createElement('input');
|
||
searchInput.type = 'text';
|
||
searchInput.placeholder = '搜索鲜花...';
|
||
searchInput.className = 'form-control mb-3';
|
||
searchInput.style.maxWidth = '300px';
|
||
searchInput.addEventListener('input', (e) => {
|
||
flowerManager.searchFlowers(e.target.value);
|
||
});
|
||
|
||
const searchContainer = document.createElement('div');
|
||
searchContainer.className = 'd-flex justify-content-center';
|
||
searchContainer.appendChild(searchInput);
|
||
|
||
const flowersSection = document.getElementById('flowers');
|
||
if (flowersSection) {
|
||
flowersSection.querySelector('.container').insertBefore(searchContainer, flowersSection.querySelector('.row'));
|
||
}
|
||
});
|
||
|
||
// 工具函数:格式化价格
|
||
function formatPrice(price) {
|
||
return '¥' + price.toFixed(2);
|
||
}
|
||
|
||
// 工具函数:显示加载状态
|
||
function showLoading() {
|
||
const container = document.getElementById('flowers-container');
|
||
container.innerHTML = `
|
||
<div class="col-12">
|
||
<div class="flower-loading">
|
||
<div class="spinner-border" role="status">
|
||
<span class="visually-hidden">加载中...</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
`;
|
||
}
|
||
|
||
// 工具函数:显示错误信息
|
||
function showError(message) {
|
||
const container = document.getElementById('flowers-container');
|
||
container.innerHTML = `
|
||
<div class="col-12">
|
||
<div class="alert alert-danger" role="alert">
|
||
<i class="fa fa-exclamation-triangle me-2"></i>
|
||
${message}
|
||
</div>
|
||
</div>
|
||
`;
|
||
} |