455 lines
14 KiB
JavaScript
455 lines
14 KiB
JavaScript
|
|
// 推广奖励功能管理类
|
|||
|
|
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);
|
|||
|
|
}
|
|||
|
|
}
|