295 lines
12 KiB
HTML
295 lines
12 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="zh-CN">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>系统管理 - NAC资产一键上链系统</title>
|
|
<link rel="stylesheet" href="/css/style.css">
|
|
</head>
|
|
<body>
|
|
<div class="container">
|
|
<header>
|
|
<div class="logo">
|
|
<h1>NAC资产一键上链系统</h1>
|
|
<p>NewAssetChain One-Click Asset Onboarding System</p>
|
|
</div>
|
|
<nav id="main-nav">
|
|
<a href="/">首页</a>
|
|
<a href="/admin/dashboard.html" class="active">系统管理</a>
|
|
<a href="#" id="logout-link">退出</a>
|
|
</nav>
|
|
</header>
|
|
|
|
<main class="dashboard">
|
|
<div class="dashboard-header">
|
|
<h2 class="dashboard-title">系统管理</h2>
|
|
</div>
|
|
|
|
<div class="stats-grid">
|
|
<div class="stat-card">
|
|
<div class="stat-icon">👥</div>
|
|
<div class="stat-label">总用户数</div>
|
|
<div class="stat-value" id="total-users">0</div>
|
|
</div>
|
|
<div class="stat-card">
|
|
<div class="stat-icon">📊</div>
|
|
<div class="stat-label">总资产数</div>
|
|
<div class="stat-value" id="total-assets">0</div>
|
|
</div>
|
|
<div class="stat-card">
|
|
<div class="stat-icon">🔄</div>
|
|
<div class="stat-label">上链记录</div>
|
|
<div class="stat-value" id="total-onboarding">0</div>
|
|
</div>
|
|
<div class="stat-card">
|
|
<div class="stat-icon">✅</div>
|
|
<div class="stat-label">成功率</div>
|
|
<div class="stat-value" id="success-rate">0%</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h3 class="card-title">用户列表</h3>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="table-container">
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>用户ID</th>
|
|
<th>用户名</th>
|
|
<th>邮箱</th>
|
|
<th>姓名</th>
|
|
<th>角色</th>
|
|
<th>创建时间</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="users-table-body">
|
|
<tr>
|
|
<td colspan="6" style="text-align: center;">加载中...</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h3 class="card-title">资产列表</h3>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="table-container">
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>资产ID</th>
|
|
<th>用户ID</th>
|
|
<th>资产类型</th>
|
|
<th>状态</th>
|
|
<th>创建时间</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="assets-table-body">
|
|
<tr>
|
|
<td colspan="5" style="text-align: center;">加载中...</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h3 class="card-title">上链记录</h3>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="table-container">
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>记录ID</th>
|
|
<th>资产ID</th>
|
|
<th>状态</th>
|
|
<th>进度</th>
|
|
<th>创建时间</th>
|
|
<th>完成时间</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="records-table-body">
|
|
<tr>
|
|
<td colspan="6" style="text-align: center;">加载中...</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</main>
|
|
|
|
<footer>
|
|
<p>© 2026 NewAssetChain. All rights reserved.</p>
|
|
<p>NAC资产一键上链系统 v1.0</p>
|
|
</footer>
|
|
</div>
|
|
|
|
<script src="/js/main.js"></script>
|
|
<script>
|
|
// 检查登录状态和管理员权限
|
|
const user = NAC.getUser();
|
|
if (!NAC.getToken() || !user || user.role !== 'admin') {
|
|
NAC.showAlert('需要管理员权限', 'error');
|
|
setTimeout(() => {
|
|
window.location.href = '/user/login.html';
|
|
}, 1500);
|
|
}
|
|
|
|
// 加载系统统计
|
|
async function loadStats() {
|
|
try {
|
|
const response = await NAC.apiRequest('/admin/stats');
|
|
if (response.success) {
|
|
const stats = response.data;
|
|
document.getElementById('total-users').textContent = stats.total_users;
|
|
document.getElementById('total-assets').textContent = stats.total_assets;
|
|
document.getElementById('total-onboarding').textContent = stats.total_onboarding;
|
|
|
|
const successRate = stats.total_onboarding > 0
|
|
? Math.round((stats.success_count / stats.total_onboarding) * 100)
|
|
: 0;
|
|
document.getElementById('success-rate').textContent = successRate + '%';
|
|
}
|
|
} catch (error) {
|
|
NAC.showAlert('加载统计数据失败', 'error');
|
|
}
|
|
}
|
|
|
|
// 加载用户列表
|
|
async function loadUsers() {
|
|
try {
|
|
const response = await NAC.apiRequest('/admin/users');
|
|
if (response.success) {
|
|
const users = response.data;
|
|
const tbody = document.getElementById('users-table-body');
|
|
|
|
if (users.length === 0) {
|
|
tbody.innerHTML = '<tr><td colspan="6" style="text-align: center;">暂无用户</td></tr>';
|
|
return;
|
|
}
|
|
|
|
tbody.innerHTML = users.map(user => `
|
|
<tr>
|
|
<td>${user.id.substring(0, 8)}...</td>
|
|
<td>${user.username}</td>
|
|
<td>${user.email}</td>
|
|
<td>${user.full_name}</td>
|
|
<td><span class="status-badge ${user.role === 'admin' ? 'status-success' : 'status-pending'}">${user.role}</span></td>
|
|
<td>${NAC.formatDate(user.created_at)}</td>
|
|
</tr>
|
|
`).join('');
|
|
}
|
|
} catch (error) {
|
|
NAC.showAlert('加载用户列表失败', 'error');
|
|
}
|
|
}
|
|
|
|
// 加载资产列表
|
|
async function loadAssets() {
|
|
try {
|
|
const response = await NAC.apiRequest('/admin/assets');
|
|
if (response.success) {
|
|
const assets = response.data;
|
|
const tbody = document.getElementById('assets-table-body');
|
|
|
|
if (assets.length === 0) {
|
|
tbody.innerHTML = '<tr><td colspan="5" style="text-align: center;">暂无资产</td></tr>';
|
|
return;
|
|
}
|
|
|
|
tbody.innerHTML = assets.map(asset => `
|
|
<tr>
|
|
<td>${asset.id.substring(0, 8)}...</td>
|
|
<td>${asset.user_id.substring(0, 8)}...</td>
|
|
<td>${asset.asset_type}</td>
|
|
<td><span class="status-badge ${NAC.getStateClass(asset.state)}">${NAC.formatState(asset.state)}</span></td>
|
|
<td>${NAC.formatDate(asset.created_at)}</td>
|
|
</tr>
|
|
`).join('');
|
|
}
|
|
} catch (error) {
|
|
NAC.showAlert('加载资产列表失败', 'error');
|
|
}
|
|
}
|
|
|
|
// 加载上链记录
|
|
async function loadRecords() {
|
|
try {
|
|
const response = await NAC.apiRequest('/admin/records');
|
|
if (response.success) {
|
|
const records = response.data;
|
|
const tbody = document.getElementById('records-table-body');
|
|
|
|
if (records.length === 0) {
|
|
tbody.innerHTML = '<tr><td colspan="6" style="text-align: center;">暂无记录</td></tr>';
|
|
return;
|
|
}
|
|
|
|
tbody.innerHTML = records.map(record => {
|
|
const progress = getProgress(record.state);
|
|
return `
|
|
<tr>
|
|
<td>${record.id.substring(0, 8)}...</td>
|
|
<td>${record.asset_id.substring(0, 8)}...</td>
|
|
<td><span class="status-badge ${NAC.getStateClass(record.state)}">${NAC.formatState(record.state)}</span></td>
|
|
<td>
|
|
<div class="progress-container">
|
|
<div class="progress-bar" style="width: ${progress}%">${progress}%</div>
|
|
</div>
|
|
</td>
|
|
<td>${NAC.formatDate(record.created_at)}</td>
|
|
<td>${record.completed_at ? NAC.formatDate(record.completed_at) : '-'}</td>
|
|
</tr>
|
|
`;
|
|
}).join('');
|
|
}
|
|
} catch (error) {
|
|
NAC.showAlert('加载上链记录失败', 'error');
|
|
}
|
|
}
|
|
|
|
// 获取进度百分比
|
|
function getProgress(state) {
|
|
const progressMap = {
|
|
'Pending': 0,
|
|
'ComplianceChecking': 11,
|
|
'Valuating': 22,
|
|
'GeneratingDNA': 33,
|
|
'Custodying': 44,
|
|
'MintingXTZH': 55,
|
|
'IssuingToken': 77,
|
|
'Listing': 88,
|
|
'Listed': 100,
|
|
'Failed': 0,
|
|
};
|
|
return progressMap[state] || 0;
|
|
}
|
|
|
|
// 页面加载时加载所有数据
|
|
loadStats();
|
|
loadUsers();
|
|
loadAssets();
|
|
loadRecords();
|
|
|
|
// 每30秒自动刷新
|
|
setInterval(() => {
|
|
loadStats();
|
|
loadUsers();
|
|
loadAssets();
|
|
loadRecords();
|
|
}, 30000);
|
|
</script>
|
|
</body>
|
|
</html>
|