432 lines
18 KiB
HTML
432 lines
18 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="/user/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>
|
|
<button class="btn btn-primary" onclick="showCreateAssetModal()">创建资产</button>
|
|
</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-assets">0</div>
|
|
</div>
|
|
<div class="stat-card">
|
|
<div class="stat-icon">⏳</div>
|
|
<div class="stat-label">待处理</div>
|
|
<div class="stat-value" id="pending-assets">0</div>
|
|
</div>
|
|
<div class="stat-card">
|
|
<div class="stat-icon">🔄</div>
|
|
<div class="stat-label">处理中</div>
|
|
<div class="stat-value" id="processing-assets">0</div>
|
|
</div>
|
|
<div class="stat-card">
|
|
<div class="stat-icon">✅</div>
|
|
<div class="stat-label">已上链</div>
|
|
<div class="stat-value" id="listed-assets">0</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="table-container">
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>资产ID</th>
|
|
<th>资产类型</th>
|
|
<th>状态</th>
|
|
<th>进度</th>
|
|
<th>创建时间</th>
|
|
<th>操作</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="assets-table-body">
|
|
<tr>
|
|
<td colspan="6" style="text-align: center;">加载中...</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</main>
|
|
|
|
<footer>
|
|
<p>© 2026 NewAssetChain. All rights reserved.</p>
|
|
<p>NAC资产一键上链系统 v1.0</p>
|
|
</footer>
|
|
</div>
|
|
|
|
<!-- 创建资产模态框 -->
|
|
<div id="create-asset-modal" class="modal">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h3 class="modal-title">创建资产</h3>
|
|
<button class="modal-close" onclick="hideCreateAssetModal()">×</button>
|
|
</div>
|
|
<form id="create-asset-form">
|
|
<div class="form-group">
|
|
<label for="asset_type">资产类型</label>
|
|
<select id="asset_type" name="asset_type" required>
|
|
<option value="">请选择</option>
|
|
<option value="real-estate">房地产</option>
|
|
<option value="equity">股权</option>
|
|
<option value="bond">债券</option>
|
|
<option value="commodity">大宗商品</option>
|
|
<option value="art">艺术品</option>
|
|
<option value="intellectual-property">知识产权</option>
|
|
<option value="other">其他</option>
|
|
</select>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="asset_name">资产名称</label>
|
|
<input type="text" id="asset_name" name="asset_name" required>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="asset_description">资产描述</label>
|
|
<textarea id="asset_description" name="asset_description" required></textarea>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="jurisdiction">管辖区域</label>
|
|
<select id="jurisdiction" name="jurisdiction" required>
|
|
<option value="">请选择</option>
|
|
<option value="CN">中国</option>
|
|
<option value="US">美国</option>
|
|
<option value="UK">英国</option>
|
|
<option value="SG">新加坡</option>
|
|
<option value="HK">香港</option>
|
|
<option value="OTHER">其他</option>
|
|
</select>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="kyc_level">KYC等级</label>
|
|
<select id="kyc_level" name="kyc_level" required>
|
|
<option value="">请选择</option>
|
|
<option value="1">Level 1 - 基础认证</option>
|
|
<option value="2">Level 2 - 标准认证</option>
|
|
<option value="3">Level 3 - 高级认证</option>
|
|
</select>
|
|
</div>
|
|
<div class="form-actions">
|
|
<button type="submit" class="btn btn-primary">创建</button>
|
|
<button type="button" class="btn btn-secondary" onclick="hideCreateAssetModal()">取消</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 上链模态框 -->
|
|
<div id="onboard-modal" class="modal">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h3 class="modal-title">提交资产上链</h3>
|
|
<button class="modal-close" onclick="hideOnboardModal()">×</button>
|
|
</div>
|
|
<form id="onboard-form">
|
|
<input type="hidden" id="onboard_asset_id">
|
|
<div class="form-group">
|
|
<label for="recipient_address">接收地址</label>
|
|
<input type="text" id="recipient_address" name="recipient_address" required placeholder="0x...">
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="custody_provider">托管服务提供商</label>
|
|
<select id="custody_provider" name="custody_provider" required>
|
|
<option value="">请选择</option>
|
|
<option value="smart_contract">智能合约托管</option>
|
|
<option value="bank">银行托管</option>
|
|
<option value="third_party">第三方托管</option>
|
|
</select>
|
|
</div>
|
|
<div class="form-actions">
|
|
<button type="submit" class="btn btn-primary">提交上链</button>
|
|
<button type="button" class="btn btn-secondary" onclick="hideOnboardModal()">取消</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 进度详情模态框 -->
|
|
<div id="progress-modal" class="modal">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h3 class="modal-title">上链进度</h3>
|
|
<button class="modal-close" onclick="hideProgressModal()">×</button>
|
|
</div>
|
|
<div id="progress-content">
|
|
<p>加载中...</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script src="/js/main.js"></script>
|
|
<script>
|
|
// 检查登录状态
|
|
if (!NAC.getToken()) {
|
|
window.location.href = '/user/login.html';
|
|
}
|
|
|
|
let assets = [];
|
|
|
|
// 加载资产列表
|
|
async function loadAssets() {
|
|
try {
|
|
const response = await NAC.apiRequest('/assets');
|
|
if (response.success) {
|
|
assets = response.data;
|
|
renderAssets();
|
|
updateStats();
|
|
}
|
|
} catch (error) {
|
|
NAC.showAlert('加载资产列表失败', 'error');
|
|
}
|
|
}
|
|
|
|
// 渲染资产列表
|
|
function renderAssets() {
|
|
const tbody = document.getElementById('assets-table-body');
|
|
if (assets.length === 0) {
|
|
tbody.innerHTML = '<tr><td colspan="6" style="text-align: center;">暂无资产</td></tr>';
|
|
return;
|
|
}
|
|
|
|
tbody.innerHTML = assets.map(asset => `
|
|
<tr>
|
|
<td>${asset.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>
|
|
<div class="progress-container">
|
|
<div class="progress-bar" style="width: ${getProgress(asset.state)}%">${getProgress(asset.state)}%</div>
|
|
</div>
|
|
</td>
|
|
<td>${NAC.formatDate(asset.created_at)}</td>
|
|
<td>
|
|
${asset.state === 'Pending' ? `<button class="btn btn-primary" onclick="showOnboardModal('${asset.id}')">上链</button>` : ''}
|
|
${asset.state === 'Failed' ? `<button class="btn btn-danger" onclick="retryOnboarding('${asset.id}')">重试</button>` : ''}
|
|
${['ComplianceChecking', 'Valuating', 'GeneratingDNA', 'Custodying', 'MintingXTZH', 'IssuingToken', 'Listing'].includes(asset.state) ? `<button class="btn btn-secondary" onclick="showProgress('${asset.id}')">查看进度</button>` : ''}
|
|
${asset.state === 'Listed' ? `<button class="btn btn-success" onclick="showProgress('${asset.id}')">查看详情</button>` : ''}
|
|
</td>
|
|
</tr>
|
|
`).join('');
|
|
}
|
|
|
|
// 更新统计数据
|
|
function updateStats() {
|
|
document.getElementById('total-assets').textContent = assets.length;
|
|
document.getElementById('pending-assets').textContent = assets.filter(a => a.state === 'Pending').length;
|
|
document.getElementById('processing-assets').textContent = assets.filter(a => ['ComplianceChecking', 'Valuating', 'GeneratingDNA', 'Custodying', 'MintingXTZH', 'IssuingToken', 'Listing'].includes(a.state)).length;
|
|
document.getElementById('listed-assets').textContent = assets.filter(a => a.state === 'Listed').length;
|
|
}
|
|
|
|
// 获取进度百分比
|
|
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;
|
|
}
|
|
|
|
// 显示创建资产模态框
|
|
function showCreateAssetModal() {
|
|
document.getElementById('create-asset-modal').classList.add('active');
|
|
}
|
|
|
|
// 隐藏创建资产模态框
|
|
function hideCreateAssetModal() {
|
|
document.getElementById('create-asset-modal').classList.remove('active');
|
|
}
|
|
|
|
// 创建资产表单提交
|
|
document.getElementById('create-asset-form').addEventListener('submit', async (e) => {
|
|
e.preventDefault();
|
|
|
|
const asset_type = document.getElementById('asset_type').value;
|
|
const asset_name = document.getElementById('asset_name').value;
|
|
const asset_description = document.getElementById('asset_description').value;
|
|
const jurisdiction = document.getElementById('jurisdiction').value;
|
|
const kyc_level = parseInt(document.getElementById('kyc_level').value);
|
|
|
|
try {
|
|
const response = await NAC.apiRequest('/assets', {
|
|
method: 'POST',
|
|
body: JSON.stringify({
|
|
asset_type,
|
|
asset_info: {
|
|
name: asset_name,
|
|
description: asset_description,
|
|
},
|
|
legal_docs: [],
|
|
kyc_level,
|
|
jurisdiction,
|
|
}),
|
|
});
|
|
|
|
if (response.success) {
|
|
NAC.showAlert('资产创建成功!', 'success');
|
|
hideCreateAssetModal();
|
|
loadAssets();
|
|
} else {
|
|
NAC.showAlert(response.message || '创建失败', 'error');
|
|
}
|
|
} catch (error) {
|
|
NAC.showAlert(error.message || '创建失败', 'error');
|
|
}
|
|
});
|
|
|
|
// 显示上链模态框
|
|
function showOnboardModal(assetId) {
|
|
document.getElementById('onboard_asset_id').value = assetId;
|
|
document.getElementById('onboard-modal').classList.add('active');
|
|
}
|
|
|
|
// 隐藏上链模态框
|
|
function hideOnboardModal() {
|
|
document.getElementById('onboard-modal').classList.remove('active');
|
|
}
|
|
|
|
// 上链表单提交
|
|
document.getElementById('onboard-form').addEventListener('submit', async (e) => {
|
|
e.preventDefault();
|
|
|
|
const asset_id = document.getElementById('onboard_asset_id').value;
|
|
const recipient_address = document.getElementById('recipient_address').value;
|
|
const custody_provider = document.getElementById('custody_provider').value;
|
|
|
|
try {
|
|
const response = await NAC.apiRequest(`/assets/${asset_id}/onboard`, {
|
|
method: 'POST',
|
|
body: JSON.stringify({ asset_id, recipient_address, custody_provider }),
|
|
});
|
|
|
|
if (response.success) {
|
|
NAC.showAlert('上链流程已启动!', 'success');
|
|
hideOnboardModal();
|
|
loadAssets();
|
|
} else {
|
|
NAC.showAlert(response.message || '提交失败', 'error');
|
|
}
|
|
} catch (error) {
|
|
NAC.showAlert(error.message || '提交失败', 'error');
|
|
}
|
|
});
|
|
|
|
// 显示进度
|
|
async function showProgress(assetId) {
|
|
document.getElementById('progress-modal').classList.add('active');
|
|
document.getElementById('progress-content').innerHTML = '<p>加载中...</p>';
|
|
|
|
try {
|
|
const response = await NAC.apiRequest(`/assets/${assetId}/progress`);
|
|
if (response.success) {
|
|
const data = response.data;
|
|
const record = data.record;
|
|
|
|
let html = `
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h4>资产ID: ${assetId.substring(0, 16)}...</h4>
|
|
<span class="status-badge ${NAC.getStateClass(data.state)}">${NAC.formatState(data.state)}</span>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="progress-container">
|
|
<div class="progress-bar" style="width: ${data.progress}%">${data.progress}%</div>
|
|
</div>
|
|
`;
|
|
|
|
if (record) {
|
|
html += `
|
|
<h4 style="margin-top: 1.5rem;">上链记录</h4>
|
|
<p><strong>记录ID:</strong> ${record.id}</p>
|
|
<p><strong>状态:</strong> ${NAC.formatState(record.state)}</p>
|
|
<p><strong>创建时间:</strong> ${NAC.formatDate(record.created_at)}</p>
|
|
${record.error_message ? `<p><strong>错误信息:</strong> ${record.error_message}</p>` : ''}
|
|
`;
|
|
}
|
|
|
|
html += `
|
|
</div>
|
|
</div>
|
|
`;
|
|
|
|
document.getElementById('progress-content').innerHTML = html;
|
|
}
|
|
} catch (error) {
|
|
document.getElementById('progress-content').innerHTML = '<p>加载失败</p>';
|
|
}
|
|
}
|
|
|
|
// 隐藏进度模态框
|
|
function hideProgressModal() {
|
|
document.getElementById('progress-modal').classList.remove('active');
|
|
}
|
|
|
|
// 重试上链
|
|
async function retryOnboarding(assetId) {
|
|
if (!confirm('确定要重试上链流程吗?')) {
|
|
return;
|
|
}
|
|
|
|
const recipient_address = prompt('请输入接收地址:');
|
|
if (!recipient_address) {
|
|
return;
|
|
}
|
|
|
|
const custody_provider = prompt('请输入托管服务提供商 (smart_contract/bank/third_party):');
|
|
if (!custody_provider) {
|
|
return;
|
|
}
|
|
|
|
try {
|
|
const response = await NAC.apiRequest(`/assets/${assetId}/retry`, {
|
|
method: 'POST',
|
|
body: JSON.stringify({ asset_id: assetId, recipient_address, custody_provider }),
|
|
});
|
|
|
|
if (response.success) {
|
|
NAC.showAlert('重试流程已启动!', 'success');
|
|
loadAssets();
|
|
} else {
|
|
NAC.showAlert(response.message || '重试失败', 'error');
|
|
}
|
|
} catch (error) {
|
|
NAC.showAlert(error.message || '重试失败', 'error');
|
|
}
|
|
}
|
|
|
|
// 页面加载时加载资产列表
|
|
loadAssets();
|
|
|
|
// 每30秒自动刷新
|
|
setInterval(loadAssets, 30000);
|
|
</script>
|
|
</body>
|
|
</html>
|