迁移会员中心脚本

This commit is contained in:
2026-04-25 14:40:54 +08:00
parent 8a690ac40d
commit dac8adfc5a
3 changed files with 441 additions and 309 deletions
@@ -1623,294 +1623,7 @@ async function generateWechatBindCode() {
</div>
</div>
<script>
(function() {
const CSRF = () => document.querySelector('meta[name="csrf-token"]')?.content ?? '';
let vipData = null;
window.openVipModal = function() {
document.getElementById('vip-modal').style.display = 'flex';
fetchVipData();
};
window.closeVipModal = function() {
document.getElementById('vip-modal').style.display = 'none';
};
window.switchVipTab = function(tabName) {
document.querySelectorAll('.vip-tab-btn').forEach(btn => btn.classList.remove('active'));
document.querySelectorAll('.vip-view-pane').forEach(pane => pane.classList.remove('active'));
document.getElementById('vip-tabbtn-' + tabName).classList.add('active');
document.getElementById('vip-view-' + tabName).classList.add('active');
};
async function fetchVipData() {
try {
const res = await fetch('{{ route('vip.center') }}', {
headers: { 'Accept': 'application/json' }
});
const json = await res.json();
if (json.status === 'success') {
vipData = json.data;
renderVipModal();
}
} catch (e) {
console.error('Failed to fetch VIP data', e);
}
}
function renderVipModal() {
const d = vipData;
// 状态栏
document.getElementById('vip-current-name').textContent = d.user.is_vip ? (d.user.vip_name || '尊贵会员') : '普通用户';
document.getElementById('vip-current-name').style.color = d.user.vip_level?.color || '#1e293b';
document.getElementById('vip-expire-time').textContent = d.user.is_vip ? `到期时间:${d.user.hy_time}` : '开通会员享特权';
document.getElementById('vip-total-amount').textContent = `¥${Number(d.totalAmount).toFixed(2)}`;
// 会员等级
const grid = document.getElementById('vip-levels-grid');
grid.innerHTML = d.vipLevels.map(v => {
const isCurrent = v.is_current;
const isHigher = v.is_higher;
const isLower = v.is_lower;
let btnText = '立即购买';
let btnColor = '#1e293b';
let btnTextColor = '#fff';
let priceToDisplay = v.price;
let isDisabled = !d.vipPaymentEnabled;
let showUpgradeInfo = false;
if (isCurrent) {
btnText = '立即续费';
btnColor = '#f59e0b';
btnTextColor = '#fff';
} else if (isHigher && d.user.is_vip) {
btnText = '补差价升级';
btnColor = '#4f46e5';
btnTextColor = '#fff';
priceToDisplay = v.upgrade_price;
showUpgradeInfo = true;
} else if (isLower) {
btnText = '无法降级';
btnColor = '#f1f5f9';
btnTextColor = '#94a3b8';
isDisabled = true;
}
return `
<div class="vip-level-card ${isCurrent ? 'current' : ''}">
${isCurrent ? '<span class="vip-level-badge">当前档位</span>' : ''}
<div style="display:flex; align-items:center; gap:10px;">
<span style="font-size:24px;">${v.icon}</span>
<span style="font-size:16px; font-weight:bold; color:${v.color}">${v.name}</span>
</div>
<div style="font-size:11px; color:#64748b; line-height:1.5; min-height:33px;">${v.description || ''}</div>
<div style="margin-top:5px; space-y:6px;">
<div class="vip-feature-item"><span class="vip-feature-icon"></span> 经验获取 <b>${v.exp_multiplier}x</b></div>
<div class="vip-feature-item"><span class="vip-feature-icon"></span> 金币获取 <b>${v.jjb_multiplier}x</b></div>
<div class="vip-feature-item"><span class="vip-feature-icon"></span> 专属入场特效 & 横幅</div>
</div>
<div style="margin-top:auto; padding-top:10px;">
<div style="font-size:18px; font-weight:900; color:#e11d48; margin-bottom:5px;">
¥${Number(priceToDisplay).toFixed(2)}
<span style="font-size:11px; font-weight:normal; color:#94a3b8;">/ ${v.duration_days}</span>
</div>
${showUpgradeInfo ? `<div style="font-size:10px; color:#4f46e5; font-weight:bold; margin-bottom:8px;">已省 ¥${(v.price - v.upgrade_price).toFixed(2)}</div>` : ''}
${!d.vipPaymentEnabled || isDisabled
? `<button ${isDisabled ? 'disabled' : 'disabled'}
style="width:100%; border:none; border-radius:8px; padding:10px; font-size:13px; font-weight:bold; cursor:not-allowed; transition:all .2s;
background:${btnColor}; color:${btnTextColor};">
${!d.vipPaymentEnabled && !isLower ? '支付暂未开启' : btnText}
</button>`
: `<div style="display:grid; grid-template-columns:1fr 1fr; gap:8px;">
<button data-vip-buy-level="${v.id}" data-vip-buy-provider="alipay"
style="border:none; border-radius:8px; padding:10px; font-size:13px; font-weight:bold; cursor:pointer; transition:all .2s; background:${btnColor}; color:${btnTextColor};">
支付宝
</button>
<button data-vip-buy-level="${v.id}" data-vip-buy-provider="wechat"
style="border:none; border-radius:8px; padding:10px; font-size:13px; font-weight:bold; cursor:pointer; transition:all .2s; background:#16a34a; color:#fff;">
微信
</button>
</div>
<div style="font-size:10px; color:#64748b; margin-top:8px; text-align:center;">${btnText}后将跳转到对应支付页面</div>`
}
</div>
</div>
`;
}).join('');
// 会员设置 Tab 显隐
const settingsBtn = document.getElementById('vip-tabbtn-settings');
if (d.user.is_vip) {
settingsBtn.style.display = 'block';
renderVipSettings();
} else {
settingsBtn.style.display = 'none';
}
// 购买记录
const logsBody = document.getElementById('vip-logs-body');
if (d.paymentLogs.length === 0) {
logsBody.innerHTML = '<tr><td colspan="5" style="padding:40px; text-align:center; color:#94a3b8;">暂无记录</td></tr>';
} else {
logsBody.innerHTML = d.paymentLogs.map(log => {
const statusMap = {
'created': { text: '待创建', class: 'background:#f1f5f9;color:#475569' },
'pending': { text: '待支付', class: 'background:#fef3c7;color:#b45309' },
'paid': { text: '已支付', class: 'background:#dcfce7;color:#166534' },
'closed': { text: '已关闭', class: 'background:#f1f5f9;color:#64748b' },
'failed': { text: '失败', class: 'background:#fee2e2;color:#991b1b' },
};
const s = statusMap[log.status] || { text: log.status, class: 'background:#f1f5f9' };
return `
<tr style="border-bottom:1px solid #f1f5f9;">
<td style="padding:10px; font-family:monospace; color:#64748b;">${log.order_no}</td>
<td style="padding:10px; font-weight:bold;">${log.vip_name}</td>
<td style="padding:10px; font-weight:bold; color:#e11d48;">¥${Number(log.amount).toFixed(2)}</td>
<td style="padding:10px;"><span style="display:inline-block; padding:2px 8px; border-radius:10px; font-size:10px; font-weight:bold; ${s.class}">${s.text}</span></td>
<td style="padding:10px; color:#64748b;">${log.opened_vip_at ? log.opened_vip_at.substring(0, 16).replace('T', ' ') : '—'}</td>
</tr>
`;
}).join('');
}
}
function renderVipSettings() {
const d = vipData;
const u = d.user;
const vl = u.vip_level;
if (!vl) return;
document.getElementById('vip-theme-icon').textContent = vl.icon || '✨';
document.getElementById('vip-theme-name').textContent = vl.name;
document.getElementById('vip-join-effect').textContent = d.effectOptions[u.custom_join_effect || vl.join_effect] || '无';
document.getElementById('vip-join-banner').textContent = `风格:${d.bannerStyleOptions[vl.join_banner] || '默认'}`;
document.getElementById('vip-leave-effect').textContent = d.effectOptions[u.custom_leave_effect || vl.leave_effect] || '无';
document.getElementById('vip-leave-banner').textContent = `风格:${d.bannerStyleOptions[vl.leave_banner] || '默认'}`;
document.getElementById('vip-default-join').textContent = vl.join_templates?.[0] || '当前档位尚未配置默认欢迎语。';
document.getElementById('vip-default-leave').textContent = vl.leave_templates?.[0] || '当前档位尚未配置默认离开语。';
const badge = document.getElementById('vip-customize-badge');
const form = document.getElementById('vip-customize-form');
const notice = document.getElementById('vip-customize-notice');
if (u.can_customize) {
badge.textContent = '已开启';
badge.style.background = '#dcfce7';
badge.style.color = '#166534';
form.style.display = 'block';
notice.style.display = 'none';
// 填充特效选项
const joinSelect = document.getElementById('vip-custom-join-effect');
const leaveSelect = document.getElementById('vip-custom-leave-effect');
let optionsHtml = '';
for (const [key, label] of Object.entries(d.effectOptions)) {
optionsHtml += `<option value="${key}">${label}</option>`;
}
joinSelect.innerHTML = optionsHtml;
leaveSelect.innerHTML = optionsHtml;
// 设置当前值
joinSelect.value = u.custom_join_effect || vl.join_effect || 'none';
leaveSelect.value = u.custom_leave_effect || vl.leave_effect || 'none';
document.getElementById('vip-custom-join').value = u.custom_join_message || '';
document.getElementById('vip-custom-leave').value = u.custom_leave_message || '';
} else {
badge.textContent = '未开放';
badge.style.background = '#f1f5f9';
badge.style.color = '#64748b';
form.style.display = 'none';
notice.style.display = 'block';
notice.textContent = u.is_vip
? '当前会员档位暂未开放个人自定义功能,不过你仍会自动使用本等级配置的专属欢迎语、离开语和华丽特效。'
: '开通会员后,这里会解锁对应等级的专属进退场主题;若等级允许,还能设置你自己的欢迎语和离开语。';
}
}
window.buyVip = function(levelId, provider = 'alipay') {
// 这里我们模拟提交表单,因为支付逻辑通常需要页面跳转
// 修改为在新窗口打开支付,避免聊天室页面丢失
const form = document.createElement('form');
form.method = 'POST';
form.action = '{{ route('vip.payment.store') }}';
form.target = '_blank'; // 新窗口打开支付
const csrfInput = document.createElement('input');
csrfInput.type = 'hidden';
csrfInput.name = '_token';
csrfInput.value = CSRF();
form.appendChild(csrfInput);
const idInput = document.createElement('input');
idInput.type = 'hidden';
idInput.name = 'vip_level_id';
idInput.value = levelId;
form.appendChild(idInput);
const providerInput = document.createElement('input');
providerInput.type = 'hidden';
providerInput.name = 'provider';
providerInput.value = provider;
form.appendChild(providerInput);
document.body.appendChild(form);
form.submit();
document.body.removeChild(form);
// 提交后关闭弹窗并提示用户
closeVipModal();
if (window.chatDialog) {
const providerText = provider === 'wechat' ? '微信支付二维码页' : '支付宝支付页';
window.chatDialog.alert(`正在为您打开${providerText},请在新页面完成支付。`, '支付提示', '#3b82f6');
}
};
window.saveVipPresenceSettings = async function() {
const joinMsg = document.getElementById('vip-custom-join').value;
const leaveMsg = document.getElementById('vip-custom-leave').value;
const joinEffect = document.getElementById('vip-custom-join-effect').value;
const leaveEffect = document.getElementById('vip-custom-leave-effect').value;
try {
const res = await fetch('{{ route('vip.center.presence.update') }}', {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
'X-CSRF-TOKEN': CSRF()
},
body: JSON.stringify({
custom_join_message: joinMsg,
custom_leave_message: leaveMsg,
custom_join_effect: joinEffect,
custom_leave_effect: leaveEffect
})
});
const json = await res.json();
if (json.status === 'success') {
window.chatDialog?.alert(json.message, '提示', '#10b981');
fetchVipData();
} else {
window.chatDialog?.alert(json.message || '保存失败', '提示', '#f59e0b');
}
} catch (e) {
window.chatDialog?.alert('网络异常,请重试', '错误', '#ef4444');
}
};
document.getElementById('vip-modal').addEventListener('click', function(e) {
if (e.target === this) closeVipModal();
});
})();
</script>
{{-- VIP 中心业务脚本已迁移到 resources/js/chat-room/vip-controls.js --}}
{{-- ═══════════ 婚姻状态弹窗 ═══════════ --}}
<style>