重构关于我们、商家申请和案例页面,优化布局和内容展示

This commit is contained in:
2025-09-18 19:52:08 +08:00
parent 10aca89915
commit 4352f613fc
45 changed files with 8513 additions and 487 deletions

435
website/js/animal.js Normal file
View File

@@ -0,0 +1,435 @@
// 动物认领功能JavaScript
class AnimalManager {
constructor() {
this.apiBaseUrl = 'https://api.jiebanke.com/api/animals';
this.animalsContainer = document.getElementById('animals-container');
this.init();
}
async init() {
await this.loadAnimals();
this.bindFilterEvents();
}
async loadAnimals() {
try {
// 模拟API调用实际项目中替换为真实API
const mockAnimals = [
{
id: 1,
name: "小白",
type: "sheep",
typeName: "绵羊",
age: "baby",
ageText: "3个月",
gender: "female",
description: "温顺可爱的小绵羊,喜欢和人亲近,非常适合初次认领者。",
status: "available",
image: "images/sheep1.svg",
price: 800,
location: "绿野农场",
health: "健康",
personality: "温顺、亲人"
},
{
id: 2,
name: "小黑",
type: "goat",
typeName: "山羊",
age: "young",
ageText: "1岁",
gender: "male",
description: "活泼好动的小山羊,喜欢探索新环境,精力充沛。",
status: "available",
image: "images/goat1.svg",
price: 600,
location: "阳光牧场",
health: "健康",
personality: "活泼、好奇"
},
{
id: 3,
name: "雪球",
type: "rabbit",
typeName: "兔子",
age: "baby",
ageText: "2个月",
gender: "female",
description: "洁白如雪的小兔子,性格温和,非常适合家庭认领。",
status: "reserved",
image: "images/rabbit1.svg",
price: 300,
location: "爱心农场",
health: "健康",
personality: "温和、安静"
},
{
id: 4,
name: "金蛋",
type: "chicken",
typeName: "鸡",
age: "adult",
ageText: "2岁",
gender: "female",
description: "产蛋能力强的母鸡,每天都能提供新鲜鸡蛋。",
status: "available",
image: "images/chicken1.svg",
price: 200,
location: "丰收农场",
health: "健康",
personality: "勤劳、温顺"
},
{
id: 5,
name: "花花",
type: "duck",
typeName: "鸭子",
age: "young",
ageText: "8个月",
gender: "female",
description: "可爱的鸭子,喜欢在水中嬉戏,性格活泼开朗。",
status: "available",
image: "images/duck1.svg",
price: 250,
location: "水乡农场",
health: "健康",
personality: "活泼、友善"
},
{
id: 6,
name: "大角",
type: "goat",
typeName: "山羊",
age: "adult",
ageText: "3岁",
gender: "male",
description: "强壮的公山羊,有着漂亮的角,性格独立但温顺。",
status: "available",
image: "images/goat2.svg",
price: 900,
location: "山野牧场",
health: "健康",
personality: "独立、温顺"
}
];
this.displayAnimals(mockAnimals);
} catch (error) {
console.error('加载动物列表失败:', error);
this.showError('加载动物列表失败,请刷新页面重试');
}
}
displayAnimals(animals) {
if (animals.length === 0) {
this.animalsContainer.innerHTML = `
<div class="col-12 text-center">
<div class="alert alert-info">
<i class="fa fa-info-circle me-2"></i>
暂无可用动物,请稍后再来查看
</div>
</div>
`;
return;
}
const animalsHTML = animals.map(animal => `
<div class="col-md-6 col-lg-4 mb-4" data-aos="fade-up">
<div class="card animal-card h-100">
<img src="${animal.image}" class="card-img-top" alt="${animal.name}">
<div class="card-body">
<div class="d-flex justify-content-between align-items-start mb-3">
<h5 class="animal-name">${animal.name}</h5>
<span class="status-badge status-${animal.status}">
${animal.status === 'available' ? '可认领' : '已被认领'}
</span>
</div>
<div class="animal-type">
<i class="fa fa-paw me-2"></i>
${animal.typeName}
</div>
<div class="animal-age">
<i class="fa fa-birthday-cake me-2"></i>
${animal.ageText}
</div>
<p class="animal-description">
${animal.description}
</p>
<div class="d-flex justify-content-between align-items-center mb-3">
<span class="text-primary fw-bold">¥${animal.price}</span>
<small class="text-muted">${animal.location}</small>
</div>
<div class="action-buttons">
<button class="btn btn-primary btn-sm"
onclick="animalManager.viewAnimalDetail(${animal.id})"
${animal.status !== 'available' ? 'disabled' : ''}>
${animal.status === 'available' ? '立即认领' : '已被认领'}
</button>
<button class="btn btn-outline-secondary btn-sm"
onclick="animalManager.showAnimalInfo(${animal.id})">
查看详情
</button>
</div>
</div>
</div>
</div>
`).join('');
this.animalsContainer.innerHTML = animalsHTML;
}
bindFilterEvents() {
const filterType = document.getElementById('filter-type');
const filterAge = document.getElementById('filter-age');
const filterStatus = document.getElementById('filter-status');
if (filterType) filterType.addEventListener('change', () => this.filterAnimals());
if (filterAge) filterAge.addEventListener('change', () => this.filterAnimals());
if (filterStatus) filterStatus.addEventListener('change', () => this.filterAnimals());
}
async filterAnimals() {
const type = document.getElementById('filter-type').value;
const age = document.getElementById('filter-age').value;
const status = document.getElementById('filter-status').value;
try {
// 模拟筛选功能
const mockAnimals = await this.loadAnimals(); // 重新加载数据
let filteredAnimals = mockAnimals;
if (type) {
filteredAnimals = filteredAnimals.filter(animal => animal.type === type);
}
if (age) {
filteredAnimals = filteredAnimals.filter(animal => animal.age === age);
}
if (status) {
filteredAnimals = filteredAnimals.filter(animal => animal.status === status);
}
this.displayAnimals(filteredAnimals);
} catch (error) {
console.error('筛选动物失败:', error);
this.showError('筛选失败,请刷新页面重试');
}
}
viewAnimalDetail(animalId) {
// 在实际项目中,这里可以跳转到详情页或显示认领表单
console.log('查看动物详情:', animalId);
// 显示认领表单模态框
this.showClaimForm(animalId);
}
showAnimalInfo(animalId) {
// 显示动物详细信息模态框
console.log('显示动物信息:', animalId);
// 这里可以显示一个包含动物详细信息的模态框
alert('动物详细信息功能开发中,即将上线');
}
showClaimForm(animalId) {
// 创建认领表单模态框
const modalHTML = `
<div class="modal fade" id="claimModal" tabindex="-1">
<div class="modal-dialog modal-lg">
<div class="modal-content animal-modal">
<div class="modal-header">
<h5 class="modal-title">认领申请</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<form id="claimForm" class="claim-form">
<input type="hidden" id="animalId" value="${animalId}">
<div class="row">
<div class="col-md-6 mb-3">
<label for="fullName" class="form-label">姓名</label>
<input type="text" class="form-control" id="fullName" required>
</div>
<div class="col-md-6 mb-3">
<label for="phone" class="form-label">手机号</label>
<input type="tel" class="form-control" id="phone" required>
</div>
</div>
<div class="mb-3">
<label for="email" class="form-label">邮箱</label>
<input type="email" class="form-control" id="email" required>
</div>
<div class="mb-3">
<label for="purpose" class="form-label">认领目的</label>
<textarea class="form-control" id="purpose" rows="3" required></textarea>
</div>
<div class="mb-3">
<label for="experience" class="form-label">饲养经验</label>
<select class="form-select" id="experience" required>
<option value="">请选择饲养经验</option>
<option value="none">无经验</option>
<option value="little">少量经验</option>
<option value="rich">丰富经验</option>
</select>
</div>
<div class="form-check mb-3">
<input class="form-check-input" type="checkbox" id="agreeTerms" required>
<label class="form-check-label" for="agreeTerms">
我已阅读并同意<a href="#" onclick="animalManager.showTerms()">认领协议</a>
</label>
</div>
<button type="submit" class="btn btn-primary btn-lg w-100">
提交认领申请
</button>
</form>
</div>
</div>
</div>
</div>
`;
// 添加模态框到页面
document.body.insertAdjacentHTML('beforeend', modalHTML);
// 显示模态框
const modal = new bootstrap.Modal(document.getElementById('claimModal'));
modal.show();
// 绑定表单提交事件
document.getElementById('claimForm').addEventListener('submit', this.handleClaimSubmit.bind(this));
// 模态框关闭时清理
document.getElementById('claimModal').addEventListener('hidden.bs.modal', function () {
this.remove();
});
}
async handleClaimSubmit(event) {
event.preventDefault();
const formData = {
animalId: document.getElementById('animalId').value,
fullName: document.getElementById('fullName').value,
phone: document.getElementById('phone').value,
email: document.getElementById('email').value,
purpose: document.getElementById('purpose').value,
experience: document.getElementById('experience').value
};
// 表单验证
if (!this.validateClaimForm(formData)) {
return;
}
try {
// 模拟API调用
console.log('提交认领申请:', formData);
// 显示成功消息
this.showSuccess('认领申请提交成功!我们会尽快联系您');
// 关闭模态框
bootstrap.Modal.getInstance(document.getElementById('claimModal')).hide();
// 重新加载动物列表
await this.loadAnimals();
} catch (error) {
console.error('提交认领申请失败:', error);
this.showError('提交失败,请稍后重试');
}
}
validateClaimForm(data) {
if (!data.fullName.trim()) {
this.showError('请输入姓名');
return false;
}
if (!data.phone.trim() || !/^1[3-9]\d{9}$/.test(data.phone)) {
this.showError('请输入正确的手机号');
return false;
}
if (!data.email.trim() || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(data.email)) {
this.showError('请输入正确的邮箱地址');
return false;
}
if (!data.purpose.trim()) {
this.showError('请输入认领目的');
return false;
}
if (!data.experience) {
this.showError('请选择饲养经验');
return false;
}
if (!document.getElementById('agreeTerms').checked) {
this.showError('请同意认领协议');
return false;
}
return true;
}
showTerms() {
alert('认领协议功能开发中,即将上线');
}
showSuccess(message) {
this.showAlert(message, 'success');
}
showError(message) {
this.showAlert(message, 'danger');
}
showAlert(message, type) {
const alertDiv = document.createElement('div');
alertDiv.className = `alert alert-${type} alert-dismissible fade show`;
alertDiv.innerHTML = `
${message}
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
`;
// 插入到页面顶部
const container = document.querySelector('.container');
container.insertBefore(alertDiv, container.firstChild);
// 5秒后自动消失
setTimeout(() => {
if (alertDiv.parentNode) {
alertDiv.remove();
}
}, 5000);
}
}
// 初始化动物管理器
const animalManager = new AnimalManager();
// 页面加载完成后初始化
document.addEventListener('DOMContentLoaded', function() {
// AOS动画初始化
if (typeof AOS !== 'undefined') {
AOS.init({
duration: 1000,
once: true
});
}
});

447
website/js/flower.js Normal file
View File

@@ -0,0 +1,447 @@
// 送花服务功能管理类
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>
`;
}

View File

@@ -32,6 +32,9 @@ document.addEventListener('DOMContentLoaded', function() {
// 初始化页面交互
initPageInteractions();
// 初始化表单处理
initForms();
});
// 创建滚动进度条
@@ -195,6 +198,50 @@ function initCallToAction() {
});
}
// 表单处理功能
function initForms() {
const forms = document.querySelectorAll('form');
forms.forEach(form => {
form.addEventListener('submit', function(e) {
e.preventDefault();
// 表单验证
if (this.checkValidity()) {
// 显示提交成功消息
showFormSuccess(this);
// 重置表单
this.reset();
} else {
// 显示验证错误
this.reportValidity();
}
});
});
}
// 显示表单提交成功消息
function showFormSuccess(form) {
// 创建成功消息
const successMessage = document.createElement('div');
successMessage.className = 'alert alert-success alert-dismissible fade show';
successMessage.innerHTML = `
<i class="fa fa-check-circle me-2"></i>
提交成功!我们会尽快与您联系。
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
`;
// 插入到表单前面
form.parentNode.insertBefore(successMessage, form);
// 5秒后自动消失
setTimeout(() => {
if (successMessage.parentNode) {
successMessage.remove();
}
}, 5000);
}
// 页面性能优化:图片懒加载
function initLazyLoading() {
if ('IntersectionObserver' in window) {

455
website/js/reward.js Normal file
View File

@@ -0,0 +1,455 @@
// 推广奖励功能管理类
class RewardManager {
constructor() {
this.promotionData = [];
this.userStats = null;
this.init();
}
// 初始化方法
init() {
this.loadPromotionData();
this.loadUserStats();
this.bindEvents();
AOS.init({
duration: 1000,
once: true
});
}
// 绑定事件
bindEvents() {
// 表单提交事件
const promotionForm = document.getElementById('promotionForm');
if (promotionForm) {
promotionForm.addEventListener('submit', (e) => {
e.preventDefault();
this.handlePromotionApplication(e.target);
});
}
// 协议链接点击事件
const agreeTerms = document.getElementById('agreeTerms');
if (agreeTerms) {
agreeTerms.addEventListener('change', (e) => {
this.toggleAgreement(e.target.checked);
});
}
// 页面加载完成后显示数据
document.addEventListener('DOMContentLoaded', () => {
this.displayPromotionStats();
});
}
// 加载推广数据(模拟数据)
loadPromotionData() {
this.promotionData = [
{
id: 1,
name: '旅行结伴推广',
commissionRate: 15,
totalEarnings: 12500,
successfulReferrals: 84,
conversionRate: 12.5
},
{
id: 2,
name: '动物认领推广',
commissionRate: 20,
totalEarnings: 8900,
successfulReferrals: 45,
conversionRate: 18.2
},
{
id: 3,
name: '送花服务推广',
commissionRate: 12,
totalEarnings: 6700,
successfulReferrals: 56,
conversionRate: 9.8
},
{
id: 4,
name: '新用户注册',
commissionRate: 10,
totalEarnings: 3200,
successfulReferrals: 320,
conversionRate: 25.4
}
];
}
// 加载用户统计数据(模拟数据)
loadUserStats() {
this.userStats = {
totalEarnings: 31300,
availableBalance: 5200,
totalReferrals: 505,
monthlyEarnings: 4200,
joinDate: '2024-01-15',
nextPayoutDate: '2024-03-15',
performanceLevel: 'Gold',
topPromotion: '旅行结伴推广'
};
}
// 显示推广统计数据
displayPromotionStats() {
// 这里可以添加实时统计数据显示逻辑
console.log('推广数据加载完成:', this.promotionData);
console.log('用户统计数据:', this.userStats);
}
// 处理推广申请
handlePromotionApplication(form) {
if (!form.checkValidity()) {
form.reportValidity();
return;
}
const formData = new FormData(form);
const applicationData = {
name: formData.get('name'),
phone: formData.get('phone'),
email: formData.get('email'),
channel: formData.get('channel'),
volume: formData.get('volume'),
message: formData.get('message'),
applicationDate: new Date().toISOString(),
status: 'pending'
};
// 模拟提交申请
this.submitPromotionApplication(applicationData);
}
// 提交推广申请
submitPromotionApplication(data) {
// 模拟API调用
console.log('提交推广申请:', data);
// 显示成功提示
this.showApplicationSuccess(data);
// 重置表单
document.getElementById('promotionForm').reset();
}
// 显示申请成功
showApplicationSuccess(data) {
// 使用SweetAlert或自定义模态框显示成功信息
if (typeof Swal !== 'undefined') {
Swal.fire({
icon: 'success',
title: '申请提交成功!',
html: `
<div class="text-start">
<p><strong>申请详情:</strong></p>
<p>姓名:${data.name}</p>
<p>电话:${data.phone}</p>
<p>邮箱:${data.email}</p>
<p>推广渠道:${this.getChannelName(data.channel)}</p>
<p class="mt-3">我们会在1-3个工作日内审核您的申请并通过邮件和短信通知您结果。</p>
</div>
`,
confirmButtonText: '确定',
confirmButtonColor: '#6c5ce7'
});
} else {
alert('推广申请提交成功我们会在1-3个工作日内联系您。');
}
}
// 获取渠道名称
getChannelName(channel) {
const channelNames = {
'wechat': '微信/朋友圈',
'weibo': '微博',
'douyin': '抖音',
'website': '个人网站/博客',
'other': '其他渠道'
};
return channelNames[channel] || channel;
}
// 切换协议同意状态
toggleAgreement(checked) {
const submitButton = document.querySelector('#promotionForm button[type="submit"]');
if (submitButton) {
submitButton.disabled = !checked;
}
}
// 生成推广链接
generatePromotionLink(userId, campaignType = 'general') {
const baseUrl = window.location.origin;
const affiliateId = this.generateAffiliateId(userId);
const campaignParams = {
'travel': 'ref=travel_affiliate',
'animal': 'ref=animal_affiliate',
'flower': 'ref=flower_affiliate',
'general': 'ref=general_affiliate'
};
return `${baseUrl}/?${campaignParams[campaignType]}&affiliate=${affiliateId}`;
}
// 生成推广ID
generateAffiliateId(userId) {
// 简单的ID生成逻辑实际应用中应该更复杂
return `aff_${userId}_${Date.now().toString(36)}`;
}
// 生成推广二维码
generatePromotionQRCode(link, elementId) {
// 这里可以集成QRCode生成库
console.log('生成二维码:', link);
// 实际实现需要使用QRCode库
}
// 复制推广链接
copyPromotionLink(link) {
navigator.clipboard.writeText(link).then(() => {
this.showCopySuccess();
}).catch(err => {
console.error('复制失败:', err);
this.showCopyError();
});
}
// 显示复制成功
showCopySuccess() {
if (typeof Swal !== 'undefined') {
Swal.fire({
icon: 'success',
title: '复制成功!',
text: '推广链接已复制到剪贴板',
timer: 2000,
showConfirmButton: false
});
} else {
alert('推广链接已复制!');
}
}
// 显示复制错误
showCopyError() {
if (typeof Swal !== 'undefined') {
Swal.fire({
icon: 'error',
title: '复制失败',
text: '请手动复制链接',
timer: 2000,
showConfirmButton: false
});
}
}
// 分享到社交媒体
shareToSocialMedia(platform, link, title = '结伴客推广') {
const shareUrls = {
'wechat': `https://api.qrserver.com/v1/create-qr-code/?size=150x150&data=${encodeURIComponent(link)}`,
'weibo': `http://service.weibo.com/share/share.php?url=${encodeURIComponent(link)}&title=${encodeURIComponent(title)}`,
'qq': `http://connect.qq.com/widget/shareqq/index.html?url=${encodeURIComponent(link)}&title=${encodeURIComponent(title)}`
};
if (shareUrls[platform]) {
window.open(shareUrls[platform], '_blank');
}
}
// 计算预计收益
calculateEstimatedEarnings(referrals, averageOrderValue, commissionRate) {
return referrals * averageOrderValue * (commissionRate / 100);
}
// 格式化金额
formatCurrency(amount) {
return new Intl.NumberFormat('zh-CN', {
style: 'currency',
currency: 'CNY'
}).format(amount);
}
// 获取性能等级
getPerformanceLevel(conversionRate) {
if (conversionRate >= 20) return 'Platinum';
if (conversionRate >= 15) return 'Gold';
if (conversionRate >= 10) return 'Silver';
return 'Bronze';
}
// 获取等级颜色
getLevelColor(level) {
const colors = {
'Platinum': '#e5e4e2',
'Gold': '#ffd700',
'Silver': '#c0c0c0',
'Bronze': '#cd7f32'
};
return colors[level] || '#6c757d';
}
}
// 页面加载完成后初始化
let rewardManager;
document.addEventListener('DOMContentLoaded', function() {
rewardManager = new RewardManager();
// 添加实时统计显示(如果需要)
addRealTimeStats();
});
// 添加实时统计显示
function addRealTimeStats() {
const statsContainer = document.createElement('div');
statsContainer.className = 'container mt-4';
statsContainer.innerHTML = `
<div class="row text-center">
<div class="col-md-3 mb-3">
<div class="reward-stat">
<div class="reward-stat-number">¥31,300</div>
<div class="reward-stat-label">总收益</div>
</div>
</div>
<div class="col-md-3 mb-3">
<div class="reward-stat">
<div class="reward-stat-number">505</div>
<div class="reward-stat-label">总推荐数</div>
</div>
</div>
<div class="col-md-3 mb-3">
<div class="reward-stat">
<div class="reward-stat-number">¥5,200</div>
<div class="reward-stat-label">可提现余额</div>
</div>
</div>
<div class="col-md-3 mb-3">
<div class="reward-stat">
<div class="reward-stat-number">Gold</div>
<div class="reward-stat-label">性能等级</div>
</div>
</div>
</div>
`;
const joinSection = document.getElementById('join');
if (joinSection) {
joinSection.parentNode.insertBefore(statsContainer, joinSection);
}
}
// 工具函数:显示加载状态
function showRewardLoading() {
const container = document.getElementById('promotion-stats');
if (container) {
container.innerHTML = `
<div class="reward-loading">
<div class="spinner-border" role="status">
<span class="visually-hidden">加载中...</span>
</div>
</div>
`;
}
}
// 工具函数:显示错误信息
function showRewardError(message) {
const container = document.getElementById('promotion-stats');
if (container) {
container.innerHTML = `
<div class="alert alert-danger" role="alert">
<i class="fa fa-exclamation-triangle me-2"></i>
${message}
</div>
`;
}
}
// 工具函数:格式化日期
function formatDate(dateString) {
return new Date(dateString).toLocaleDateString('zh-CN', {
year: 'numeric',
month: 'long',
day: 'numeric'
});
}
// 工具函数生成进度条HTML
function createProgressBar(value, max = 100, type = 'primary') {
const percentage = (value / max) * 100;
return `
<div class="progress mb-2">
<div class="progress-bar progress-bar-${type}"
role="progressbar"
style="width: ${percentage}%"
aria-valuenow="${value}"
aria-valuemin="0"
aria-valuemax="${max}">
${percentage.toFixed(1)}%
</div>
</div>
`;
}
// 推广链接生成器(示例)
function setupPromotionLinkGenerator() {
const generatorHtml = `
<div class="card mt-4">
<div class="card-header">
<h5 class="mb-0">推广链接生成器</h5>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-6 mb-3">
<label class="form-label">推广类型</label>
<select class="form-select" id="promotionType">
<option value="general">通用推广</option>
<option value="travel">旅行结伴</option>
<option value="animal">动物认领</option>
<option value="flower">送花服务</option>
</select>
</div>
<div class="col-md-6 mb-3">
<label class="form-label">用户ID</label>
<input type="text" class="form-control" id="userId" placeholder="输入用户ID">
</div>
</div>
<div class="mb-3">
<label class="form-label">推广链接</label>
<div class="input-group">
<input type="text" class="form-control" id="generatedLink" readonly>
<button class="btn btn-outline-secondary" type="button" onclick="copyGeneratedLink()">
<i class="fa fa-copy"></i>
</button>
</div>
</div>
<button class="btn btn-primary" onclick="generatePromotionLink()">
生成链接
</button>
</div>
</div>
`;
const joinSection = document.getElementById('join');
if (joinSection) {
joinSection.insertAdjacentHTML('beforebegin', generatorHtml);
}
}
// 全局函数供HTML调用
function generatePromotionLink() {
const type = document.getElementById('promotionType').value;
const userId = document.getElementById('userId').value || 'demo_user';
const link = rewardManager.generatePromotionLink(userId, type);
document.getElementById('generatedLink').value = link;
}
function copyGeneratedLink() {
const linkInput = document.getElementById('generatedLink');
if (linkInput.value) {
rewardManager.copyPromotionLink(linkInput.value);
}
}

266
website/js/travel.js Normal file
View File

@@ -0,0 +1,266 @@
// 旅行结伴功能JavaScript
class TravelPlanManager {
constructor() {
this.apiBaseUrl = 'https://api.jiebanke.com/api/travel';
this.plansContainer = document.getElementById('travel-plans-container');
this.travelForm = document.getElementById('travel-plan-form');
this.init();
}
async init() {
await this.loadTravelPlans();
this.bindEvents();
}
async loadTravelPlans() {
try {
// 模拟API调用实际项目中替换为真实API
const mockPlans = [
{
id: 1,
destination: "西藏拉萨",
travelDate: "2025-03-15",
duration: 10,
budget: "5000-10000",
description: "寻找志同道合的伙伴一起探索西藏的神秘与美丽,计划游览布达拉宫、大昭寺、纳木错等景点。",
requirements: "年龄25-35岁有高原旅行经验者优先",
participants: 3,
maxParticipants: 6,
creator: "旅行达人小李",
createdAt: "2025-01-15"
},
{
id: 2,
destination: "云南大理",
travelDate: "2025-02-20",
duration: 7,
budget: "2000-5000",
description: "大理古城、洱海、苍山七日游,体验白族文化和自然风光。",
requirements: "喜欢摄影、热爱自然",
participants: 2,
maxParticipants: 4,
creator: "摄影师小王",
createdAt: "2025-01-10"
},
{
id: 3,
destination: "海南三亚",
travelDate: "2025-04-01",
duration: 5,
budget: "3000-6000",
description: "阳光沙滩度假之旅,潜水、冲浪、海鲜美食一网打尽。",
requirements: "性格开朗,喜欢水上运动",
participants: 4,
maxParticipants: 8,
creator: "阳光少年小张",
createdAt: "2025-01-08"
}
];
this.displayPlans(mockPlans);
} catch (error) {
console.error('加载旅行计划失败:', error);
this.showError('加载旅行计划失败,请刷新页面重试');
}
}
displayPlans(plans) {
if (plans.length === 0) {
this.plansContainer.innerHTML = `
<div class="col-12 text-center">
<div class="alert alert-info">
<i class="fa fa-info-circle me-2"></i>
暂无旅行计划,快来发布第一个吧!
</div>
</div>
`;
return;
}
const plansHTML = plans.map(plan => `
<div class="col-md-6 col-lg-4 mb-4" data-aos="fade-up">
<div class="card travel-plan-card h-100">
<div class="card-body">
<div class="d-flex justify-content-between align-items-start mb-3">
<h5 class="destination">${plan.destination}</h5>
<span class="budget-badge">${plan.budget}元</span>
</div>
<div class="mb-3">
<div class="travel-date mb-2">
<i class="fa fa-calendar-alt me-2"></i>
出发日期: ${new Date(plan.travelDate).toLocaleDateString('zh-CN')}
</div>
<div class="travel-date">
<i class="fa fa-clock me-2"></i>
行程天数: ${plan.duration}
</div>
</div>
<p class="card-text text-muted mb-3" style="font-size: 0.9rem;">
${plan.description}
</p>
<div class="mb-3">
<small class="text-muted">
<i class="fa fa-user me-1"></i>
伙伴要求: ${plan.requirements || '无特殊要求'}
</small>
</div>
<div class="d-flex justify-content-between align-items-center">
<div class="participants">
<i class="fa fa-users"></i>
<span>${plan.participants}/${plan.maxParticipants}人</span>
</div>
<small class="text-muted">发布者: ${plan.creator}</small>
</div>
<div class="action-buttons mt-3">
<button class="btn btn-primary btn-sm" onclick="travelManager.joinPlan(${plan.id})">
加入计划
</button>
<button class="btn btn-outline-secondary btn-sm" onclick="travelManager.viewPlanDetail(${plan.id})">
查看详情
</button>
</div>
</div>
</div>
</div>
`).join('');
this.plansContainer.innerHTML = plansHTML;
}
bindEvents() {
if (this.travelForm) {
this.travelForm.addEventListener('submit', this.handleFormSubmit.bind(this));
}
}
async handleFormSubmit(event) {
event.preventDefault();
const formData = new FormData(this.travelForm);
const planData = {
destination: document.getElementById('destination').value,
travelDate: document.getElementById('travel-date').value,
duration: parseInt(document.getElementById('duration').value),
budget: document.getElementById('budget').value,
description: document.getElementById('description').value,
requirements: document.getElementById('requirements').value
};
// 表单验证
if (!this.validateForm(planData)) {
return;
}
try {
// 模拟API调用
console.log('发布旅行计划:', planData);
// 显示成功消息
this.showSuccess('旅行计划发布成功!');
// 清空表单
this.travelForm.reset();
// 重新加载计划列表
await this.loadTravelPlans();
} catch (error) {
console.error('发布旅行计划失败:', error);
this.showError('发布失败,请稍后重试');
}
}
validateForm(data) {
if (!data.destination.trim()) {
this.showError('请输入目的地');
return false;
}
if (!data.travelDate) {
this.showError('请选择出发日期');
return false;
}
if (data.duration < 1) {
this.showError('行程天数必须大于0');
return false;
}
if (!data.budget) {
this.showError('请选择预算范围');
return false;
}
if (!data.description.trim()) {
this.showError('请输入行程描述');
return false;
}
return true;
}
async joinPlan(planId) {
try {
// 模拟加入计划
console.log('加入旅行计划:', planId);
this.showSuccess('已申请加入旅行计划,等待创建者确认');
} catch (error) {
console.error('加入计划失败:', error);
this.showError('加入失败,请稍后重试');
}
}
viewPlanDetail(planId) {
// 在实际项目中,这里可以跳转到详情页或显示模态框
console.log('查看旅行计划详情:', planId);
alert('功能开发中,即将上线');
}
showSuccess(message) {
this.showAlert(message, 'success');
}
showError(message) {
this.showAlert(message, 'danger');
}
showAlert(message, type) {
const alertDiv = document.createElement('div');
alertDiv.className = `alert alert-${type} alert-dismissible fade show`;
alertDiv.innerHTML = `
${message}
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
`;
// 插入到页面顶部
const container = document.querySelector('.container');
container.insertBefore(alertDiv, container.firstChild);
// 5秒后自动消失
setTimeout(() => {
if (alertDiv.parentNode) {
alertDiv.remove();
}
}, 5000);
}
}
// 初始化旅行计划管理器
const travelManager = new TravelPlanManager();
// 页面加载完成后初始化
document.addEventListener('DOMContentLoaded', function() {
// AOS动画初始化
if (typeof AOS !== 'undefined') {
AOS.init({
duration: 1000,
once: true
});
}
});