feat: 查看钱包优化,地址增加链上查询

This commit is contained in:
example
2026-09-28 21:11:08 +08:00
parent 5b677d4d1f
commit 8f7469cc4e
10 changed files with 313 additions and 88 deletions
+103 -38
View File
@@ -28,9 +28,27 @@
}
.mn-wallet-table th { background: #fafafa; font-weight: 600; white-space: nowrap; }
.mn-wallet-table .addr-cell {
word-break: break-all;
font-family: Menlo, Monaco, Consolas, monospace;
max-width: 280px;
max-width: 360px;
vertical-align: middle;
}
.mn-wallet-table .addr-cell .addr-row {
display: flex;
align-items: center;
gap: 8px;
min-width: 0;
}
.mn-wallet-table .addr-cell .addr-text {
flex: 1 1 auto;
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.mn-wallet-table .addr-cell .mn-explorer {
flex: 0 0 auto;
font-family: inherit;
white-space: nowrap;
}
.mn-wallet-table .coin-cell { white-space: nowrap; font-variant-numeric: tabular-nums; }
.mn-inactive {
@@ -45,6 +63,7 @@
border-radius: 3px;
vertical-align: middle;
}
.mn-updating { color: #1e9fff; }
</style>
<div class="layui-card">
<form class="layui-form layui-card-header layuiadmin-card-header-auto" lay-filter="LAY-mn-search">
@@ -114,13 +133,40 @@ layui.use(['table', 'form', 'layer'], function () {
return (v === null || v === undefined || v === '') ? '—' : esc(v);
}
function explorerUrl(chain, address) {
var addr = String(address || '').trim();
if (!addr) return '';
var c = String(chain || '').trim().toUpperCase();
if (c === 'TRON' || c === 'TRX') return 'https://tronscan.org/#/address/' + encodeURIComponent(addr);
if (c === 'ETH' || c === 'ETHEREUM' || c === 'EVM') return 'https://etherscan.io/address/' + encodeURIComponent(addr);
if (c === 'BSC' || c === 'BNB' || c === 'BINANCE') return 'https://bscscan.com/address/' + encodeURIComponent(addr);
if (c === 'BTC' || c === 'BITCOIN') return 'https://mempool.space/address/' + encodeURIComponent(addr);
if (c === 'SOL' || c === 'SOLANA') return 'https://solscan.io/account/' + encodeURIComponent(addr);
return '';
}
function addrCellHtml(r) {
var addr = r.address || '';
var url = explorerUrl(r.chain_type, addr);
var html = '<td class="addr-cell"><div class="addr-row">';
html += '<span class="addr-text" title="' + esc(addr) + '">' + esc(addr) + '</span>';
if (url) {
html += '<a class="layui-btn layui-btn-primary layui-btn-xs mn-explorer" href="' + esc(url) +
'" target="_blank" rel="noopener noreferrer">链上查询</a>';
}
html += '</div></td>';
return html;
}
function renderWalletsHtml(payload) {
var rows = (payload && payload.addresses) || [];
var html = '<div class="mn-wallet-wrap">';
html += '<div class="mn-wallet-hd">';
html += '<div class="mn-wallet-meta">助记词 #' + esc(payload.mnemonic_id) +
(payload.source ? ' · ' + esc(payload.source) : '') +
' · 关联地址 ' + rows.length + ' 个</div>';
' · 关联地址 ' + rows.length + ' 个' +
(payload.updating ? ' · <span class="mn-updating">正在更新</span>' : '') +
'</div>';
if (rows.length && payload.refresh_url) {
html += '<button type="button" class="layui-btn layui-btn-sm" id="LAY-mn-refresh-bal">刷新余额</button>';
}
@@ -139,7 +185,7 @@ layui.use(['table', 'form', 'layer'], function () {
'<td>' + (r.id == null || r.id === '' ? '—' : esc(r.id)) + '</td>' +
'<td>' + esc(r.chain_type || '—') +
(inactive ? '<span class="mn-inactive">未激活</span>' : '') + '</td>' +
'<td class="addr-cell">' + esc(r.address) + '</td>' +
addrCellHtml(r) +
'<td>' + (r.derive_index == null || r.derive_index === '' ? '—' : esc(r.derive_index)) + '</td>' +
'<td class="coin-cell">' + coinVal(r.usdt) + '</td>' +
'<td class="coin-cell">' + coinVal(r.trx) + '</td>' +
@@ -166,25 +212,36 @@ layui.use(['table', 'form', 'layer'], function () {
bindRefresh(layero, payload);
}
function bindRefresh(layero, payload) {
function bindRefresh(layero, payload, auto) {
layero.find('#LAY-mn-refresh-bal').off('click').on('click', function () {
var btn = $(this);
if (btn.prop('disabled')) return;
if (!payload.refresh_url) return;
btn.prop('disabled', true).addClass('layui-btn-disabled');
var loadIdx = layer.load(1, { shade: 0.1 });
$.ajax({
url: payload.refresh_url,
method: 'POST',
data: { _token: token },
success: function (res) {
layer.close(loadIdx);
if (!res || res.code !== 0) {
btn.prop('disabled', false).removeClass('layui-btn-disabled');
return layer.msg((res && res.msg) || '刷新失败');
}
var next = res.data || {};
applyWalletsHtml(layero, next);
runWalletRefresh(layero, payload, false);
});
if (auto && payload.updating && payload.refresh_url) {
runWalletRefresh(layero, payload, true);
}
}
function runWalletRefresh(layero, payload, auto) {
var btn = layero.find('#LAY-mn-refresh-bal');
if (!payload.refresh_url) return;
if (btn.prop('disabled') && !auto) return;
btn.prop('disabled', true).addClass('layui-btn-disabled');
var loadIdx = auto ? null : layer.load(1, { shade: 0.1 });
$.ajax({
url: payload.refresh_url,
method: 'POST',
data: { _token: token },
success: function (res) {
if (loadIdx != null) layer.close(loadIdx);
if (!res || res.code !== 0) {
btn.prop('disabled', false).removeClass('layui-btn-disabled');
if (!auto) layer.msg((res && res.msg) || '刷新失败');
return;
}
var next = res.data || {};
next.updating = false;
applyWalletsHtml(layero, next);
if (!auto) {
var ok = Number(next.refreshed || 0);
var fail = Number(next.failed || 0);
layer.msg(fail ? ('已写入地址表 ' + ok + ' 个,失败 ' + fail + ' 个') : ('已写入地址表 ' + ok + ' 个'));
@@ -194,22 +251,30 @@ layui.use(['table', 'form', 'layer'], function () {
setTimeout(function () {
nextBtn.prop('disabled', false).removeClass('layui-btn-disabled');
}, cooldown * 1000);
},
error: function (xhr) {
layer.close(loadIdx);
var body = xhr.responseJSON || {};
var retry = body.data && body.data.retry_after ? Number(body.data.retry_after) : 0;
if (xhr.status === 429 && retry > 0) {
layer.msg(body.msg || ('请 ' + retry + ' 秒后再试'));
setTimeout(function () {
btn.prop('disabled', false).removeClass('layui-btn-disabled');
}, retry * 1000);
return;
}
btn.prop('disabled', false).removeClass('layui-btn-disabled');
layer.msg(body.msg || body.message || '刷新失败');
}
});
},
error: function (xhr) {
if (loadIdx != null) layer.close(loadIdx);
var body = xhr.responseJSON || {};
var retry = body.data && body.data.retry_after ? Number(body.data.retry_after) : 0;
if (xhr.status === 429) {
if (!auto) layer.msg(body.msg || ('请 ' + retry + ' 秒后再试'));
payload.updating = false;
applyWalletsHtml(layero, payload);
if (!auto && retry > 0) {
var nextBtn = layero.find('#LAY-mn-refresh-bal');
nextBtn.prop('disabled', true).addClass('layui-btn-disabled');
setTimeout(function () {
nextBtn.prop('disabled', false).removeClass('layui-btn-disabled');
}, retry * 1000);
}
return;
}
btn.prop('disabled', false).removeClass('layui-btn-disabled');
payload.updating = false;
applyWalletsHtml(layero, payload);
if (!auto) layer.msg(body.msg || body.message || '刷新失败');
}
});
}
@@ -234,7 +299,7 @@ layui.use(['table', 'form', 'layer'], function () {
shadeClose: true,
content: renderWalletsHtml(payload),
success: function (layero) {
bindRefresh(layero, payload);
bindRefresh(layero, payload, true);
}
});
},