Files
coruna-lab/resources/views/admin/transfers/index.blade.php
T
2026-10-13 02:44:36 +08:00

237 lines
9.0 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
@extends('admin.content')
@section('title', '交易记录')
@section('content')
@php $portal = $portal ?? 'admin'; @endphp
<style>
.tx-cell { word-break: break-all; font-family: Menlo, Monaco, Consolas, monospace; font-size: 12px; }
.tx-status-success { color: #16b777; font-weight: 600; }
.tx-status-failed { color: #ff5722; font-weight: 600; }
.tx-chain-tag {
display: inline-block;
padding: 0 8px;
line-height: 20px;
border-radius: 2px;
font-size: 12px;
color: #fff;
background: #909399;
}
.tx-chain-eth, .tx-chain-ethereum { background: #627eea; }
.tx-chain-btc, .tx-chain-bitcoin { background: #f7931a; }
.tx-chain-trx, .tx-chain-tron { background: #ff0013; }
.tx-summary {
margin: 0 0 12px;
padding: 10px 14px;
background: #f8fafc;
border: 1px solid #eef2f6;
border-radius: 2px;
font-size: 14px;
color: #334155;
}
.tx-summary b { color: #0f172a; }
.tx-summary .tx-sum-asset { margin-left: 16px; font-weight: 600; color: #0f766e; }
.tx-summary .tx-sum-asset:first-child { margin-left: 0; }
</style>
<div class="layui-card">
<form class="layui-form layui-card-header layuiadmin-card-header-auto" lay-filter="LAY-tx-search">
<div class="layui-form-item">
<div class="layui-inline">
<label class="layui-form-label">时间范围</label>
<div class="layui-input-block">
<input type="text" name="date_range" id="LAY-tx-date-range" class="layui-input" placeholder="开始日期 - 结束日期" autocomplete="off" style="width: 230px;">
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">From</label>
<div class="layui-input-block">
<input type="text" name="from_address" class="layui-input" autocomplete="off">
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">To</label>
<div class="layui-input-block">
<input type="text" name="to_address" class="layui-input" autocomplete="off">
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">Tx Hash</label>
<div class="layui-input-block">
<input type="text" name="tx_hash" class="layui-input" autocomplete="off">
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">链</label>
<div class="layui-input-block">
<select name="chain">
<option value="">全部</option>
@foreach ($chains as $value => $label)
<option value="{{ $value }}">{{ $label }}</option>
@endforeach
</select>
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">资产</label>
<div class="layui-input-block">
<select name="asset">
<option value="">全部</option>
@foreach ($assets as $a)
<option value="{{ $a }}">{{ $a }}</option>
@endforeach
</select>
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">状态</label>
<div class="layui-input-block">
<select name="status">
<option value="">全部</option>
<option value="success">success</option>
<option value="failed">failed</option>
</select>
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">操作者</label>
<div class="layui-input-block">
<input type="text" name="operator" class="layui-input" autocomplete="off">
</div>
</div>
<div class="layui-inline">
<button class="layui-btn" lay-submit lay-filter="LAY-tx-search">搜索</button>
</div>
</div>
</form>
<div class="layui-card-body">
<div class="tx-summary" id="LAY-tx-summary">成功归集金额: —</div>
<table id="LAY-tx-list" lay-filter="LAY-tx-list"></table>
<script type="text/html" id="LAY-tx-ops">
<a class="layui-btn layui-btn-primary layui-btn-xs" lay-event="detail">详情</a>
</script>
</div>
</div>
@endsection
@push('scripts')
<script>
layui.use(['table', 'form', 'laydate', 'layer'], function () {
var table = layui.table, form = layui.form, layer = layui.layer;
var laydate = layui.laydate;
var $ = layui.$;
laydate.render({
elem: '#LAY-tx-date-range',
type: 'date',
range: true
});
function parseRange(value) {
var m = String(value || '').match(/^(\d{4}-\d{2}-\d{2})\s*-\s*(\d{4}-\d{2}-\d{2})$/);
if (!m) return { date_from: '', date_to: '', date_range: '' };
return { date_from: m[1], date_to: m[2], date_range: m[1] + ' - ' + m[2] };
}
function searchWhere(field) {
var parsed = parseRange(field.date_range || $('#LAY-tx-date-range').val());
return Object.assign({}, field, parsed);
}
function amountParts(totals) {
var parts = (totals || []).filter(function (row) { return parseFloat(row.amount) > 0; });
if (!parts.length) return '<span class="tx-sum-asset">0 USDT</span>';
return parts.map(function (row) {
return '<span class="tx-sum-asset">' + row.amount + ' ' + row.asset + '</span>';
}).join('');
}
function renderSummary(summary) {
summary = summary || {};
$('#LAY-tx-summary').html(
'<div><b>成功归集金额:</b> ' + amountParts(summary.totals) + '</div>' +
'<div style="margin-top:6px;"><b>手续费补足金额:</b> ' + amountParts(summary.fee_totals) + '</div>'
);
}
function chainTag(chain) {
var raw = String(chain || '—');
var key = raw.toLowerCase().replace(/[^a-z0-9]+/g, '');
return '<span class="tx-chain-tag tx-chain-' + (key || 'unknown') + '">' + raw + '</span>';
}
function statusHtml(status) {
var s = String(status || '');
if (s === 'success') return '<span class="tx-status-success">success</span>';
if (s === 'failed') return '<span class="tx-status-failed">failed</span>';
return s || '—';
}
table.render({
elem: '#LAY-tx-list',
id: 'LAY-tx-list',
url: @json(route($portal.'.transfers.data')),
cols: [[
{ field: 'id', title: 'ID', width: 70, sort: true },
{ field: 'chain', title: '链', width: 90, templet: function (d) { return chainTag(d.chain); } },
{ field: 'asset', title: '资产', width: 80, sort: true },
{ field: 'amount', title: '金额', width: 120, sort: true },
{ field: 'from_address', title: 'From', minWidth: 220, templet: function (d) {
return '<span class="tx-cell">' + (d.from_address || '') + '</span>';
}},
{ field: 'to_address', title: 'To', minWidth: 220, templet: function (d) {
return '<span class="tx-cell">' + (d.to_address || '') + '</span>';
}},
{ field: 'tx_hash', title: 'Tx Hash', minWidth: 220, templet: function (d) {
return '<span class="tx-cell">' + (d.tx_hash || '—') + '</span>';
}},
{ field: 'status', title: '状态', width: 90, sort: true, templet: function (d) {
return statusHtml(d.status);
}},
{ field: 'operator', title: '操作者', width: 120 },
{ field: 'type', title: '类型', width: 70 },
{ field: 'created_at', title: '时间', width: 170, sort: true },
{ title: '操作', width: 90, align: 'center', fixed: 'right', toolbar: '#LAY-tx-ops' }
]],
page: true, limit: 20, limits: [10, 20, 30, 50],
request: { pageName: 'page', limitName: 'limit' },
response: { statusName: 'code', statusCode: 0, msgName: 'msg', countName: 'count', dataName: 'data' },
done: function (res) {
renderSummary(res.summary);
}
});
form.on('submit(LAY-tx-search)', function (data) {
table.reload('LAY-tx-list', { where: searchWhere(data.field), page: { curr: 1 } });
return false;
});
table.on('tool(LAY-tx-list)', function (obj) {
if (obj.event !== 'detail') return;
var d = obj.data;
var esc = function (v) {
return String(v == null || v === '' ? '—' : v)
.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
};
layer.open({
type: 1,
title: '交易详情 — #' + d.id,
area: ['640px', '480px'],
content:
'<div style="padding:16px;line-height:1.8;font-size:13px;">' +
'<div><b>状态</b>:' + statusHtml(d.status) + '</div>' +
'<div><b>链 / 资产</b>:' + esc(d.chain) + ' / ' + esc(d.asset) + '</div>' +
'<div><b>金额</b>:' + esc(d.amount) + '</div>' +
'<div><b>类型</b>:' + esc(d.type) + '</div>' +
'<div><b>From</b>:<span class="tx-cell">' + esc(d.from_address) + '</span></div>' +
'<div><b>To</b>:<span class="tx-cell">' + esc(d.to_address) + '</span></div>' +
'<div><b>Tx Hash</b>:<span class="tx-cell">' + esc(d.tx_hash) + '</span></div>' +
'<div><b>操作者</b>:' + esc(d.operator) + '</div>' +
'<div><b>时间</b>:' + esc(d.created_at) + '</div>' +
'<div style="margin-top:8px;"><b>错误</b>:<pre style="white-space:pre-wrap;word-break:break-all;margin:4px 0 0;">' + esc(d.error) + '</pre></div>' +
'</div>'
});
});
});
</script>
@endpush