Files
SMANAGE/TempLate/pages/private/CreateE/StoreValue.html
T

306 lines
10 KiB
HTML

<script src="/assets/gerp/GERPThemeSync.js"></script>
<link rel="stylesheet" href="/assets/css/GERP.css">
<style>
.sv-container {
padding: 24px;
max-width: 1100px;
margin: 0 auto;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
color: var(--TextPrimary, #1e293b);
}
.sv-section {
background: var(--CardBackground, #fff);
border: 1px solid var(--BorderColor, #e2e8f0);
border-radius: 12px;
overflow: hidden;
margin-bottom: 24px;
}
.sv-section-header {
background: var(--PrimaryColor, #2563eb);
color: #fff;
padding: 14px 20px;
display: flex;
align-items: center;
justify-content: space-between;
}
.sv-section-header h2 {
margin: 0;
font-size: 17px;
font-weight: 600;
color: #fff;
}
.sv-section-body { padding: 20px; }
.sv-table {
width: 100%;
border-collapse: collapse;
font-size: 13px;
}
.sv-table th,
.sv-table td {
border: 1px solid var(--BorderColor, #e2e8f0);
padding: 8px 10px;
text-align: left;
}
.sv-table th {
background: var(--BackgroundColor, #f5f5f5);
font-weight: 600;
color: var(--TextSecondary, #64748b);
}
.sv-table tr:hover td { background: var(--HoverBackground, rgba(0,0,0,0.03)); }
/* td.sv-empty 选择器优先级高于 .sv-table td,确保空状态居中 */
.sv-table td.sv-empty {
text-align: center;
padding: 28px;
color: var(--TextSecondary, #64748b);
}
.sv-table td.sv-empty i {
font-size: 28px;
display: block;
margin-bottom: 8px;
opacity: 0.4;
}
.sv-cash-btn {
padding: 5px 12px;
border: none;
border-radius: 5px;
background: var(--DangerColor, #ef4444);
color: #fff;
cursor: pointer;
font-size: 12px;
}
.sv-cash-btn:hover { opacity: 0.9; }
.sv-cash-btn:disabled { opacity: 0.5; cursor: not-allowed; }
.sv-loading {
display: inline-block;
animation: sv-spin 1s linear infinite;
}
@keyframes sv-spin { to { transform: rotate(360deg); } }
.sv-btn-ghost {
background: rgba(255,255,255,0.2);
color: #fff;
border: none;
padding: 6px 14px;
border-radius: 6px;
cursor: pointer;
font-size: 13px;
}
.sv-btn-ghost:hover { opacity: 0.9; }
/* Toast */
.sv-toast-wrap {
position: fixed;
bottom: 16px;
right: 16px;
z-index: 9999;
display: flex;
flex-direction: column;
gap: 8px;
}
.sv-toast {
padding: 10px 14px;
border-radius: 6px;
color: #fff;
font-size: 13px;
box-shadow: 0 4px 12px rgba(0,0,0,0.2);
animation: sv-toast-in 0.25s ease-out;
display: flex;
align-items: center;
gap: 8px;
}
.sv-toast.out { animation: sv-toast-out 0.25s ease-in forwards; }
@keyframes sv-toast-in {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
@keyframes sv-toast-out {
from { opacity: 1; }
to { opacity: 0; transform: translateY(-8px); }
}
</style>
<div class="sv-container">
<div class="sv-section">
<div class="sv-section-header">
<h2>已购买储值项目</h2>
<button id="refresh-btn" class="sv-btn-ghost">刷新</button>
</div>
<div class="sv-section-body">
<div style="overflow-x:auto;">
<table class="sv-table">
<thead>
<tr>
<th>玩家名称</th>
<th>储值类型</th>
<th>创建时间</th>
<th>最短取出时间</th>
<th>已存日期</th>
<th>日利率</th>
<th>储值金额</th>
<th>累计利息</th>
<th>生效长度</th>
<th>操作</th>
</tr>
</thead>
<tbody id="storage-table-body">
<tr><td colspan="10" class="sv-empty"><i class="fas fa-spinner sv-loading"></i><p>加载中...</p></td></tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
<div class="sv-toast-wrap" id="toast-wrap"></div>
<script>
(function () {
'use strict';
function showToast(message, type) {
const wrap = document.getElementById('toast-wrap');
const t = document.createElement('div');
t.className = 'sv-toast';
const colors = {
success: '#10b981', danger: '#ef4444',
warning: '#f59e0b', info: '#3b82f6'
};
t.style.background = colors[type || 'info'] || colors.info;
const icons = {
success: 'fa-check-circle', danger: 'fa-exclamation-circle',
warning: 'fa-exclamation-triangle', info: 'fa-info-circle'
};
t.innerHTML = '<i class="fas ' + (icons[type || 'info'] || icons.info) + '"></i><span>' + message + '</span>';
wrap.appendChild(t);
setTimeout(function () {
t.classList.add('out');
setTimeout(function () { t.remove(); }, 260);
}, 3000);
}
function formatNum(n) {
if (n === null || n === undefined || isNaN(n)) return '0';
return Number(n).toLocaleString();
}
function fetchStorageData() {
const tbody = document.getElementById('storage-table-body');
tbody.innerHTML = '<tr><td colspan="10" class="sv-empty"><i class="fas fa-spinner sv-loading"></i><p>加载中...</p></td></tr>';
fetch('/API/StoredValue/GetStoreValue', { credentials: 'include' })
.then(function (r) {
if (!r.ok) throw new Error('Network error');
return r.json();
})
.then(function (data) {
if (data.status === 0 && Array.isArray(data.data)) {
if (data.data.length > 0) {
tbody.innerHTML = data.data.map(function (item) {
return '<tr>' +
'<td>' + (item.PlayerName || '') + '</td>' +
'<td>' + (item.StoreValueType || '') + '</td>' +
'<td>' + (item.StoreValueCreateDateTime || '') + '</td>' +
'<td>' + (item.StoreValueMin || '') + '</td>' +
'<td>' + formatNum(item.GameDays) + ' 游戏日 / ' + formatNum(item.Days) + ' 现实日</td>' +
'<td>' + (item.StoreValueDayInterestRate || 0) + '</td>' +
'<td>' + formatNum(item.StoreValueAmount) + ' GC</td>' +
'<td>' + formatNum(item.AccruedInterest) + ' GC</td>' +
'<td>' + (item.StoreValueExpirationGameDate || '') + ' 游戏日</td>' +
'<td><button class="sv-cash-btn" data-uuid="' + item.StoreValueUUID + '">兑现</button></td>' +
'</tr>';
}).join('');
document.querySelectorAll('.sv-cash-btn').forEach(function (btn) {
btn.addEventListener('click', function () { handleCash(btn); });
});
} else {
tbody.innerHTML = '<tr><td colspan="10" class="sv-empty"><i class="fas fa-inbox"></i><p>暂无储值数据</p></td></tr>';
}
} else {
tbody.innerHTML = '<tr><td colspan="10" class="sv-empty"><i class="fas fa-exclamation-circle"></i><p>' + (data.msg || '加载失败') + '</p></td></tr>';
}
})
.catch(function (err) {
console.error('fetchStorageData error:', err);
tbody.innerHTML = '<tr><td colspan="10" class="sv-empty"><i class="fas fa-exclamation-circle"></i><p>加载失败,请重试</p></td></tr>';
});
}
function handleCash(btn) {
const uuid = btn.getAttribute('data-uuid');
btn.disabled = true;
btn.textContent = '处理中...';
fetch('/API/StoredValue/Cash', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify({ StoreValueUUID: uuid })
})
.then(function (r) { return r.json(); })
.then(function (data) {
if (data.status === 0) {
showToast('兑现成功', 'success');
fetchStorageData();
} else {
showToast(data.msg || '兑现失败', 'danger');
btn.disabled = false;
btn.textContent = '兑现';
}
})
.catch(function (err) {
console.error('handleCash error:', err);
showToast('网络错误,兑现失败', 'danger');
btn.disabled = false;
btn.textContent = '兑现';
});
}
document.getElementById('refresh-btn').addEventListener('click', fetchStorageData);
fetchStorageData();
})();
// ==================== GERP 主题同步 ====================
window.addEventListener('load', function () {
const CheckAndInit = () => {
if (window.GERPThemeSync) {
window.GERPThemeSync.init();
return;
}
setTimeout(CheckAndInit, 100);
};
CheckAndInit();
if (window.parent !== window) {
window.parent.postMessage({ type: 'GET_THEME' }, '*');
}
});
window.addEventListener('message', function (e) {
if (e.data && e.data.type === 'THEME_CHANGE') {
const colors = e.data.colors || (e.data.data && e.data.data.colors);
if (colors) {
const root = document.documentElement;
Object.entries(colors).forEach(([key, value]) => {
root.style.setProperty('--' + key, value);
});
}
}
});
</script>