// 转账历史管理
class TransferHistory {
constructor() {
this.storageKey = 'bsc_transfer_history';
this.history = this.loadHistory();
this.filteredHistory = [...this.history];
this.initElements();
this.bindEvents();
this.render();
}
initElements() {
// 筛选器
this.statusFilter = document.getElementById('statusFilter');
this.typeFilter = document.getElementById('typeFilter');
this.searchInput = document.getElementById('searchInput');
// 操作按钮
this.exportBtn = document.getElementById('exportHistory');
this.clearBtn = document.getElementById('clearHistory');
// 统计
this.totalSuccess = document.getElementById('totalSuccess');
this.totalFailed = document.getElementById('totalFailed');
this.totalPending = document.getElementById('totalPending');
this.totalTransfers = document.getElementById('totalTransfers');
this.recordCount = document.getElementById('recordCount');
// 表格
this.tableBody = document.getElementById('historyTableBody');
// 模态框
this.detailModal = document.getElementById('detailModal');
this.closeDetailBtn = document.getElementById('closeDetail');
this.viewOnBscscanBtn = document.getElementById('viewOnBscscan');
}
bindEvents() {
// 筛选器事件
this.statusFilter.addEventListener('change', () => this.applyFilters());
this.typeFilter.addEventListener('change', () => this.applyFilters());
this.searchInput.addEventListener('input', () => this.applyFilters());
// 操作按钮
this.exportBtn.addEventListener('click', () => this.exportToCSV());
this.clearBtn.addEventListener('click', () => this.clearHistory());
// 模态框
this.closeDetailBtn.addEventListener('click', () => this.closeModal());
this.detailModal.querySelector('.modal-close').addEventListener('click', () => this.closeModal());
this.detailModal.addEventListener('click', (e) => {
if (e.target === this.detailModal) this.closeModal();
});
}
// 从localStorage加载历史记录
loadHistory() {
try {
const data = localStorage.getItem(this.storageKey);
return data ? JSON.parse(data) : [];
} catch (error) {
console.error('加载历史记录失败:', error);
return [];
}
}
// 保存历史记录到localStorage
saveHistory() {
try {
localStorage.setItem(this.storageKey, JSON.stringify(this.history));
} catch (error) {
console.error('保存历史记录失败:', error);
showNotification('保存失败', 'error');
}
}
// 应用筛选
applyFilters() {
const status = this.statusFilter.value;
const type = this.typeFilter.value;
const search = this.searchInput.value.toLowerCase().trim();
this.filteredHistory = this.history.filter(record => {
// 状态筛选
if (status !== 'all' && record.status !== status) return false;
// 类型筛选
if (type !== 'all' && record.type !== type) return false;
// 搜索筛选
if (search) {
const searchableText = [
record.address,
record.txHash,
record.note
].join(' ').toLowerCase();
if (!searchableText.includes(search)) return false;
}
return true;
});
this.render();
}
// 渲染页面
render() {
this.renderStats();
this.renderTable();
}
// 渲染统计数据
renderStats() {
const stats = {
success: 0,
failed: 0,
pending: 0,
total: this.history.length
};
this.history.forEach(record => {
if (record.status === 'success') stats.success++;
else if (record.status === 'failed') stats.failed++;
else if (record.status === 'pending') stats.pending++;
});
this.totalSuccess.textContent = stats.success;
this.totalFailed.textContent = stats.failed;
this.totalPending.textContent = stats.pending;
this.totalTransfers.textContent = stats.total;
this.recordCount.textContent = this.filteredHistory.length;
}
// 渲染表格
renderTable() {
if (this.filteredHistory.length === 0) {
this.tableBody.innerHTML = `
${this.history.length === 0 ? '暂无转账记录' : '没有符合条件的记录'}
|
`;
return;
}
// 按时间倒序排列
const sortedHistory = [...this.filteredHistory].sort((a, b) => b.timestamp - a.timestamp);
this.tableBody.innerHTML = sortedHistory.map(record => `
| ${this.formatTime(record.timestamp)} |
${record.type === 'bnb' ? 'BNB' : record.tokenSymbol || 'Token'}
|
${this.formatAddress(record.address)}
|
${record.amount} ${record.type === 'bnb' ? 'BNB' : record.tokenSymbol || ''}
|
${this.getStatusText(record.status)}
|
${record.txHash ? `
${this.formatTxHash(record.txHash)}
` : '-'}
|
${record.note || '-'} |
|
`).join('');
}
// 显示详情模态框
showDetail(recordId) {
const record = this.history.find(r => r.id === recordId);
if (!record) return;
document.getElementById('detailTime').textContent = this.formatTime(record.timestamp, true);
document.getElementById('detailType').textContent = record.type === 'bnb' ? 'BNB' : `${record.tokenSymbol || 'Token'} (${record.tokenAddress})`;
document.getElementById('detailAddress').textContent = record.address;
document.getElementById('detailAmount').textContent = `${record.amount} ${record.type === 'bnb' ? 'BNB' : record.tokenSymbol || ''}`;
document.getElementById('detailStatus').innerHTML = `${this.getStatusText(record.status)}`;
document.getElementById('detailTxHash').textContent = record.txHash || '-';
document.getElementById('detailNote').textContent = record.note || '-';
document.getElementById('detailGas').textContent = record.gasCost ? `${record.gasCost} BNB` : '-';
if (record.txHash) {
this.viewOnBscscanBtn.href = `https://bscscan.com/tx/${record.txHash}`;
this.viewOnBscscanBtn.style.display = 'inline-flex';
} else {
this.viewOnBscscanBtn.style.display = 'none';
}
this.detailModal.style.display = 'flex';
}
// 关闭模态框
closeModal() {
this.detailModal.style.display = 'none';
}
// 导出为CSV
exportToCSV() {
if (this.filteredHistory.length === 0) {
showNotification('没有可导出的记录', 'warning');
return;
}
const headers = ['时间', '类型', '收款地址', '金额', '状态', '交易哈希', '备注', 'Gas费用'];
const rows = this.filteredHistory.map(record => [
this.formatTime(record.timestamp, true),
record.type === 'bnb' ? 'BNB' : record.tokenSymbol || 'Token',
record.address,
`${record.amount} ${record.type === 'bnb' ? 'BNB' : record.tokenSymbol || ''}`,
this.getStatusText(record.status),
record.txHash || '',
record.note || '',
record.gasCost || ''
]);
const csvContent = [headers, ...rows]
.map(row => row.map(cell => `"${cell}"`).join(','))
.join('\n');
const blob = new Blob(['\ufeff' + csvContent], { type: 'text/csv;charset=utf-8;' });
const link = document.createElement('a');
link.href = URL.createObjectURL(blob);
link.download = `transfer_history_${Date.now()}.csv`;
link.click();
showNotification('导出成功', 'success');
}
// 清空历史记录
clearHistory() {
if (this.history.length === 0) {
showNotification('没有可清空的记录', 'warning');
return;
}
if (!confirm('确定要清空所有历史记录吗?此操作不可恢复!')) {
return;
}
this.history = [];
this.filteredHistory = [];
this.saveHistory();
this.render();
showNotification('历史记录已清空', 'success');
}
// 格式化时间
formatTime(timestamp, full = false) {
const date = new Date(timestamp);
if (full) {
return date.toLocaleString('zh-CN', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit'
});
}
return date.toLocaleString('zh-CN', {
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit'
});
}
// 格式化地址
formatAddress(address) {
if (!address) return '-';
return `${address.slice(0, 6)}...${address.slice(-4)}`;
}
// 格式化交易哈希
formatTxHash(txHash) {
if (!txHash) return '-';
return `${txHash.slice(0, 8)}...${txHash.slice(-6)}`;
}
// 获取状态文本
getStatusText(status) {
const statusMap = {
'success': '成功',
'failed': '失败',
'pending': '待确认'
};
return statusMap[status] || status;
}
}
// 初始化
let historyManager;
document.addEventListener('DOMContentLoaded', () => {
historyManager = new TransferHistory();
// 将实例暴露到全局,供onclick使用
window.history = historyManager;
});