strong all

This commit is contained in:
2026-01-19 21:14:58 +08:00
parent 5364edfc46
commit 1129376981
10 changed files with 5827 additions and 2090 deletions

View File

@@ -258,7 +258,7 @@
<tr class="header-row">
<td colspan="3" align="center">
<h1>内部库存管控系统 V4.2 (非密级)</h1>
<p>当前登录: OPERATOR_8821 | <a href="#" onclick="alert('模拟注销')">[注销]</a> | <a href="#">[切换节点]</a> | <a href="#">[系统日志]</a> | <a href="#">[报错]</a></p>
<p>当前登录: OPERATOR_8821 | <a href="#" onclick="showCustomAlert('模拟注销')">[注销]</a> | <a href="#">[切换节点]</a> | <a href="#">[系统日志]</a> | <a href="#">[报错]</a></p>
</td>
</tr>
<tr>
@@ -708,12 +708,70 @@
</div>
</div>
<!-- 6. 通用确认 模态框 -->
<div class="modal-overlay" id="confirmModal">
<div class="modal-window" style="width: 400px; min-height: auto;">
<div class="modal-header">
<h3 class="modal-title">操作确认</h3>
<span class="modal-close" onclick="closeModal('confirmModal')">&times;</span>
</div>
<div class="modal-body">
<p id="confirmMessage" style="font-size: 1rem; color: #334155;">确定执行此操作?</p>
</div>
<div class="modal-footer">
<button class="page-btn" onclick="closeModal('confirmModal')">取消</button>
<button class="page-btn active" id="confirmBtnAction">确定</button>
</div>
</div>
</div>
<!-- 7. 通用提示 模态框 (替代 alert) -->
<div class="modal-overlay" id="alertModal">
<div class="modal-window" style="width: 400px; min-height: auto;">
<div class="modal-header">
<h3 class="modal-title">系统提示</h3>
<span class="modal-close" onclick="closeModal('alertModal')">&times;</span>
</div>
<div class="modal-body">
<p id="alertMessage" style="font-size: 1rem; color: #334155; white-space: pre-line;"></p>
</div>
<div class="modal-footer">
<button class="page-btn active" onclick="closeModal('alertModal')">知道了</button>
</div>
</div>
</div>
<!-- Toast 通知容器 -->
<div class="toast-container" id="toastContainer"></div>
<script>
// === JavaScript 核心逻辑重构 (SPA模式) ===
// --- 自定义弹窗逻辑 (替代原生 alert/confirm) ---
let onConfirmCallback = null;
function showCustomAlert(msg) {
document.getElementById('alertMessage').innerText = msg;
openModal('alertModal');
}
function showCustomConfirm(msg, callback) {
document.getElementById('confirmMessage').innerText = msg;
onConfirmCallback = callback;
openModal('confirmModal');
}
// 初始化绑定 Confirm 按钮事件
document.addEventListener('DOMContentLoaded', () => {
document.getElementById('confirmBtnAction').addEventListener('click', () => {
if (typeof onConfirmCallback === 'function') {
onConfirmCallback();
}
closeModal('confirmModal');
});
});
// 配置与状态
const CONFIG = {
totalItems: 358, // 模拟总数据量
@@ -1094,17 +1152,17 @@
}
function printDetail() {
alert("正在连接打印机... \n(模拟: 发送指令 PCL_PRINT_JOB_001)");
showCustomAlert("正在连接打印机... \n(模拟: 发送指令 PCL_PRINT_JOB_001)");
}
// 删除项目
function deleteItem(id, btnElement) {
if(confirm(`确定要删除物料 ${id} 吗?`)) {
showCustomConfirm(`确定要删除物料 ${id} 吗?`, () => {
// 这只是前端模拟,实际应该发请求
state.data = state.data.filter(d => d.id !== id);
applyFilter(); // 重新走一遍筛选和排序
showToast(`物料 ${id} 已删除`, "warning");
}
});
}
// 批量操作

File diff suppressed because it is too large Load Diff

View File

@@ -113,6 +113,30 @@
/* 分页 */
.pagination { display: flex; align-items: center; justify-content: flex-end; padding: 15px; gap: 10px; }
.pagination button { background: #fff; border: 1px solid #d9d9d9; padding: 5px 10px; border-radius: 4px; cursor: pointer; }
/* === New Interactive Elements === */
/* Modal */
.modal-overlay { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.5); display: none; justify-content: center; align-items: center; z-index: 1000; }
.modal-content { background: #fff; width: 500px; padding: 20px; border-radius: 4px; box-shadow: 0 4px 12px rgba(0,0,0,0.15); animation: fadeIn 0.3s; }
.modal-header { font-size: 16px; font-weight: bold; margin-bottom: 15px; border-bottom: 1px solid #eee; padding-bottom: 10px; display: flex; justify-content: space-between; }
/* Drawer (Right Panel) */
.drawer-overlay { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.2); z-index: 900; display: none; }
.drawer { position: fixed; top: 0; right: -450px; width: 450px; height: 100%; background: #fff; box-shadow: -2px 0 8px rgba(0,0,0,0.1); transition: right 0.3s ease; z-index: 901; display: flex; flex-direction: column; }
.drawer.open { right: 0; }
.drawer-header { padding: 20px; border-bottom: 1px solid #eee; background: #fafafa; display: flex; justify-content: space-between; align-items: center; }
.drawer-body { padding: 20px; flex: 1; overflow-y: auto; }
/* Toast Notification */
.toast { position: fixed; top: 20px; left: 50%; transform: translateX(-50%); background: #333; color: #fff; padding: 10px 20px; border-radius: 4px; z-index: 2000; display: none; opacity: 0; transition: opacity 0.3s; }
.toast.show { display: block; opacity: 1; }
/* Form Styles */
.form-group { margin-bottom: 15px; }
.form-group label { display: block; margin-bottom: 5px; color: #666; font-weight: 500; }
.form-input { width: 100%; padding: 8px; border: 1px solid #d9d9d9; border-radius: 4px; box-sizing: border-box; }
@keyframes fadeIn { from { opacity: 0; transform: translateY(-10px); } to { opacity: 1; transform: translateY(0); } }
</style>
</head>
<body>
@@ -137,10 +161,10 @@
<div class="sidebar">
<h3>资源列表</h3>
<ul>
<li><a href="#" class="active">全部实例 (14)</a></li>
<li><a href="#">运行中 (10)</a></li>
<li><a href="#">已停止 (3)</a></li>
<li><a href="#">异常/维护 (1)</a></li>
<li><a href="javascript:void(0)" class="active" onclick="filterByStatus('all', this)">全部实例 (14)</a></li>
<li><a href="javascript:void(0)" onclick="filterByStatus('running', this)">运行中 (10)</a></li>
<li><a href="javascript:void(0)" onclick="filterByStatus('stopped', this)">已停止 (3)</a></li>
<li><a href="javascript:void(0)" onclick="filterByStatus('maintenance', this)">异常/维护 (1)</a></li>
</ul>
<h3>配额监控</h3>
@@ -169,7 +193,7 @@
<form class="search-bar">
<fieldset>
<label>关键词:</label> <input type="text" placeholder="Instance ID / Name">
<label>关键词:</label> <input type="text" id="searchInput" placeholder="Instance ID / Name">
<label>标签:</label> <input type="text" placeholder="Key:Value">
<label>付费类型:</label>
<select>
@@ -178,17 +202,18 @@
<option>按量付费</option>
<option>抢占式实例</option>
</select>
<button type="button" class="btn-primary" onclick="alert('Searching...')">刷新列表</button>
<button type="button">重置</button>
<button type="button" class="btn-primary" onclick="searchInstances()">刷新列表</button>
<button type="button" onclick="resetSearch()">重置</button>
</fieldset>
</form>
<div class="toolbar">
<button>启动</button>
<button>停止</button>
<button>重启</button>
<button>释放设置</button>
<button>修改计费模式</button>
<button style="background: var(--primary); color: #fff; border-color: var(--primary);" onclick="openCreateModal()">+ 创建实例</button>
<button onclick="performToolbarAction('start')">启动</button>
<button onclick="performToolbarAction('stop')">停止</button>
<button onclick="performToolbarAction('restart')">重启</button>
<button onclick="showToast('功能开发中: 修改释放设置', 'warning')">释放设置</button>
<button onclick="showToast('功能开发中: 修改计费模式', 'warning')">修改计费模式</button>
</div>
<div class="instance-list">
@@ -221,11 +246,11 @@
<span class="status-running">运行中</span>
</div>
<div class="action-group">
<button>远程连接</button>
<button>监控</button>
<button>更多...</button>
<button class="btn-danger" onclick="confirmDelete()">强制停止</button>
<button class="btn-danger" onclick="confirmDelete()">彻底销毁</button>
<button onclick="remoteConnect('i-bp1j2k3l4m5n')">远程连接</button>
<button onclick="openMonitor('i-bp1j2k3l4m5n')">监控</button>
<button onclick="showMoreMenu(this)">更多...</button>
<button class="btn-danger" onclick="confirmDelete('i-bp1j2k3l4m5n')">强制停止</button>
<button class="btn-danger" onclick="confirmDelete('i-bp1j2k3l4m5n', true)">彻底销毁</button>
</div>
</div>
@@ -275,8 +300,8 @@
<span>未开通</span>
</div>
<div class="action-group">
<button style="color: #fa8c16; font-weight:bold;">立即开通</button>
<button>了解详情</button>
<button style="color: #fa8c16; font-weight:bold;" onclick="openProductIntro('scaling')">立即开通</button>
<button onclick="openProductIntro('scaling_doc')">了解详情</button>
</div>
</div>
@@ -404,7 +429,7 @@
</div>
<div style="grid-column: 1 / -1; margin-top: 5px;">
<p>请及时充值,以免影响实例的正常运行。</p>
<button style="background: #f5222d; color: white; border: none; padding: 4px 12px; border-radius: 2px;">立即充值</button>
<button onclick="openRecharge()" style="background: #f5222d; color: white; border: none; padding: 4px 12px; border-radius: 2px;">立即充值</button>
</div>
</div>
@@ -438,10 +463,10 @@
</div>
<div class="pagination">
<button>&lt; 上一页</button>
<span>第 1 / 5 页</span>
<button>下一页 &gt;</button>
<select>
<button onclick="changePage(-1)">&lt; 上一页</button>
<span id="pageInfo">第 1 / 5 页</span>
<button onclick="changePage(1)">下一页 &gt;</button>
<select onchange="changePageSize(this)">
<option>每页 10 条</option>
<option>每页 20 条</option>
<option>每页 50 条</option>
@@ -457,9 +482,159 @@
</div>
<script>
// 脚本逻辑:处理全选和危险操作确认
<!-- Components -->
<!-- Create Instance Modal -->
<div id="createModal" class="modal-overlay">
<div class="modal-content">
<div class="modal-header">
<span>创建新实例 (ECI)</span>
<span onclick="closeCreateModal()" style="cursor:pointer; color:#999;"></span>
</div>
<div class="form-group">
<label>实例名称</label>
<input type="text" id="newInstanceName" class="form-input" placeholder="例如: Web-Server-02">
</div>
<div class="form-group">
<label>镜像</label>
<select id="newInstanceImage" class="form-input">
<option value="Ubuntu 22.04 LTS">Ubuntu 22.04 LTS</option>
<option value="CentOS 7.9">CentOS 7.9</option>
<option value="Aliyun Linux 3">Aliyun Linux 3</option>
<option value="Windows Server 2022">Windows Server 2022</option>
</select>
</div>
<div class="form-group">
<label>规格</label>
<select id="newInstanceType" class="form-input">
<option value="2 vCPU / 4 GiB">ecs.t6-c1m2.large (2 vCPU / 4 GiB)</option>
<option value="4 vCPU / 8 GiB">ecs.c7.xlarge (4 vCPU / 8 GiB)</option>
<option value="8 vCPU / 16 GiB">ecs.g7.2xlarge (8 vCPU / 16 GiB)</option>
</select>
</div>
<div style="text-align: right; margin-top: 20px;">
<button onclick="closeCreateModal()" style="margin-right: 10px; padding: 6px 15px; border: 1px solid #d9d9d9; background: #fff; cursor: pointer; border-radius: 4px;">取消</button>
<button onclick="confirmCreate()" style="padding: 6px 15px; background: var(--primary); color: #fff; border: none; cursor: pointer; border-radius: 4px;">立即购买</button>
</div>
</div>
</div>
<!-- Instance Detail Drawer -->
<div id="drawerOverlay" class="drawer-overlay" onclick="closeDrawer()"></div>
<div id="detailDrawer" class="drawer">
<div class="drawer-header">
<h3 id="drawerTitle">Instance Details</h3>
<button onclick="closeDrawer()" style="border:none; background:none; cursor:pointer; font-size:16px;"></button>
</div>
<div class="drawer-body">
<div style="background: #f5f5f5; padding: 15px; border-radius: 4px; margin-bottom: 20px;">
<p><strong>Status:</strong> <span style="color:green">Running</span></p>
<p><strong>Region:</strong> CN-East-2 (Zone B)</p>
<p><strong>Public IP:</strong> 139.196.128.44</p>
<p><strong>Private IP:</strong> 192.168.1.101</p>
</div>
<h4>监控概览 (1 Hour)</h4>
<div style="height: 100px; background: #fafafa; border: 1px solid #eee; display: flex; align-items: flex-end; padding: 10px; gap: 5px;">
<!-- Fake Chart Bars -->
<div style="width: 10%; height: 30%; background: #badde8;"></div>
<div style="width: 10%; height: 50%; background: #badde8;"></div>
<div style="width: 10%; height: 80%; background: #108ee9;"></div>
<div style="width: 10%; height: 60%; background: #badde8;"></div>
<div style="width: 10%; height: 40%; background: #badde8;"></div>
<div style="width: 10%; height: 90%; background: #f04134;"></div>
<div style="width: 10%; height: 50%; background: #badde8;"></div>
<div style="width: 10%; height: 30%; background: #badde8;"></div>
</div>
<h4 style="margin-top:20px;">配置信息</h4>
<ul style="line-height:2; color:#666;">
<li>Instance Type: ecs.g7.xlarge</li>
<li>Image ID: ubuntu_22_04_x64_20G_alibase</li>
<li>Security Group: sg-bp12345678</li>
<li>VPC ID: vpc-bp1abcdefg</li>
</ul>
</div>
</div>
<div id="toast" class="toast">Action Successful</div>
<script>
// --- State Management ---
// Toast
function showToast(msg) {
const t = document.getElementById('toast');
t.innerText = msg;
t.classList.add('show');
setTimeout(() => t.classList.remove('show'), 3000);
}
// Modal Logic
function openCreateModal() {
document.getElementById('createModal').style.display = 'flex';
}
function closeCreateModal() {
document.getElementById('createModal').style.display = 'none';
document.getElementById('newInstanceName').value = '';
}
function confirmCreate() {
showToast('订单已提交,实例正在初始化...');
closeCreateModal();
// Here we could simulate adding a row, but for static demo toast is enough
setTimeout(() => {
// Simulate "Created" by navigating or refreshing? No, just an alert.
// Ideally we add a row to DOM
addInstanceRow();
}, 1000);
}
function addInstanceRow() {
const name = document.getElementById('newInstanceName').value || 'New-Instance-' + Math.floor(Math.random()*1000);
const list = document.querySelector('.instance-list');
const newRow = document.createElement('div');
newRow.className = 'list-row';
newRow.innerHTML = `
<div><input type="checkbox" class="row-checkbox"></div>
<div>
<strong onclick="openDrawer('${name}')">${name}</strong><br>
<small>镜像: Ubuntu 22.04</small>
</div>
<div><span>Checking...</span><br><span style="color:#999">192.168.1.${Math.floor(Math.random()*255)}</span></div>
<div><span>2 vCPU</span><br><span>4 GiB</span></div>
<div><span class="status-running" style="color:#fa8c16">启动中...</span></div>
<div class="action-group">
<button>管理</button>
</div>
`;
// Insert after header
list.insertBefore(newRow, list.children[1]);
}
// Drawer Logic
function openDrawer(name) {
document.getElementById('drawerTitle').innerText = name || 'Instance Details';
document.getElementById('drawerOverlay').style.display = 'block';
setTimeout(() => document.getElementById('detailDrawer').classList.add('open'), 10);
}
function closeDrawer() {
document.getElementById('detailDrawer').classList.remove('open');
setTimeout(() => document.getElementById('drawerOverlay').style.display = 'none', 300);
}
// Bind click events for all existing instance names
document.querySelectorAll('.list-row strong').forEach(el => {
// Remove old onclick
el.removeAttribute('onclick');
el.addEventListener('click', function() {
// Get name text
const name = this.innerText.split('(')[0].trim() || 'Instance';
openDrawer(name);
});
});
// Toolbar Actions
// 全选/取消全选
document.getElementById('selectAll').addEventListener('change', function(e) {
const checkboxes = document.querySelectorAll('.row-checkbox');
@@ -468,15 +643,174 @@
});
});
function performAction(action) {
// Get selected
const checkboxes = document.querySelectorAll('.row-checkbox:checked');
if (checkboxes.length === 0) {
alert('请先选择至少一个实例');
return;
}
const count = checkboxes.length;
if(confirm(`确定要对选中的 ${count} 台实例执行 [${action.toUpperCase()}] 操作吗?`)) {
showToast(`指令已下发: ${action.toUpperCase()} ${count} instances`);
// Reset selection
checkboxes.forEach(c => c.checked = false);
document.getElementById('selectAll').checked = false;
}
}
// 危险操作二次确认
function confirmDelete() {
const userInput = prompt("这是一个高风险操作!\n请输入 'DELETE' 以确认销毁该实例:");
if (userInput === 'DELETE') {
alert('操作已提交:实例正在销毁中...');
showToast('操作已提交:实例正在销毁中...');
}
}
// -------------------------------------------------------------------------
// Enhanced Interactivity (New)
// -------------------------------------------------------------------------
// 1. Sidebar Filter
function filterByStatus(status, el) {
// Update URL hash for simulation
window.location.hash = status;
// Active state
document.querySelectorAll('.sidebar li a').forEach(a => a.classList.remove('active'));
if(el) el.classList.add('active');
const rows = document.querySelectorAll('.list-row:not(.ad-row):not(.billing-alert-row)');
rows.forEach(row => {
const statusText = row.querySelector('div:nth-child(5)').innerText.trim();
let show = false;
if (status === 'all') show = true;
else if (status === 'running' && (statusText.includes('运行中') || statusText.includes('启动中'))) show = true;
else if (status === 'stopped' && statusText.includes('已停止')) show = true;
else if (status === 'maintenance' && statusText.includes('维护')) show = true;
row.style.display = show ? 'grid' : 'none';
});
showToast(`已筛选: ${el ? el.innerText : status}`);
}
// 2. Toolbar Logic (Renamed to avoid conflict)
function performToolbarAction(action) {
// Re-use existing logic, just better naming
const checkboxes = document.querySelectorAll('.row-checkbox:checked');
if (checkboxes.length === 0) {
alert('请先勾选需要操作的实例');
return;
}
showToast(`正在对 ${checkboxes.length} 台实例执行 [${action}]...`);
setTimeout(() => {
showToast('操作指令已下发');
checkboxes.forEach(c => c.checked = false);
document.getElementById('selectAll').checked = false;
}, 800);
}
// 3. Row Actions
function remoteConnect(instanceId) {
const width = 800;
const height = 600;
const left = (screen.width - width) / 2;
const top = (screen.height - height) / 2;
// Open a fake terminal window
const win = window.open("", "_blank", `width=${width},height=${height},top=${top},left=${left}`);
win.document.write(`
<body style="background:#000; color:#0f0; font-family:monospace; padding:20px;">
<p>Connecting to ${instanceId}...</p>
<p>Authenticating...</p>
<p>Welcome to Ubuntu 22.04 LTS</p>
<p>root@${instanceId}:~# <span id="cursor">_</span></p>
<script>
setInterval(() => {
const c = document.getElementById('cursor');
c.style.visibility = c.style.visibility === 'hidden' ? 'visible' : 'hidden';
}, 500);
<\/script>
</body>
`);
}
function openMonitor(instanceId) {
openDrawer(instanceId + ' - 实时监控');
}
function showMoreMenu(btn) {
// Simple fallback
const actions = ['创建快照', '变更配置', '重置密码', '更换操作系统'];
const action = prompt(`[${actions.join(' | ')}]\n请输入要执行的操作:`, actions[0]);
if(action) {
showToast(`正在执行: ${action}`);
}
}
// 4. Search Bar
function searchInstances() {
const val = document.getElementById('searchInput').value;
if(!val) {
// refresh
showToast('刷新列表成功');
// reset filters
filterByStatus('all', document.querySelector('.sidebar a.active'));
} else {
alert('操作已取消。');
showToast(`正在搜索 "${val}"...`);
}
}
function resetSearch() {
document.getElementById('searchInput').value = '';
// Trigger input event to clear filter
document.getElementById('searchInput').dispatchEvent(new Event('input'));
showToast('搜索条件已重置');
}
// 5. Pagination
let currentPage = 1;
function changePage(dir) {
const newPage = currentPage + dir;
if(newPage < 1 || newPage > 5) return;
currentPage = newPage;
document.getElementById('pageInfo').innerText = `${currentPage} / 5 页`;
// Fake loading effect
const list = document.querySelector('.instance-list');
list.style.opacity = '0.5';
setTimeout(() => {
list.style.opacity = '1';
// Scroll to top
list.scrollIntoView({behavior: "smooth"});
}, 300);
}
function changePageSize(select) {
showToast(`分页设置已更新: ${select.value}`);
}
// 6. Billing & Ads
function openRecharge() {
if(confirm("将跳转至支付网关 (Alipay/WeChat)...")) {
showToast("正在跳转支付页面...");
}
}
function openProductIntro(product) {
showToast(`正在打开产品文档: ${product}...`);
}
// Override generic confirmDelete
window.confirmDelete = function(instanceId, isHard) {
if(confirm(`警告: 确定要${isHard ? '彻底销毁' : '强制停止'}实例 [${instanceId}] 吗?\n此操作不可逆!`)) {
showToast('操作已提交');
}
};
</script>
</body>

View File

@@ -302,7 +302,7 @@
<fieldset>
<legend>附件下载</legend>
<p>文件: Minidump_20251221.zip (256 KB)</p>
<a href="#" onclick="alert('开始下载真实文件...')">[点击下载附件]</a>
<a href="#" onclick="showCustomAlert('开始下载真实文件...')">[点击下载附件]</a>
</fieldset>
<div align="center" class="fake-download-area">
@@ -570,6 +570,35 @@
</div>
<!-- Modals -->
<div class="modal-backdrop" id="confirmModal">
<div class="modal-panel" style="width: 400px;">
<div class="card-header">
操作确认 <span style="cursor:pointer; float:right;" onclick="closeModal('confirmModal')">&times;</span>
</div>
<div class="card-body">
<p id="confirmMessage" style="margin-bottom: 20px;">确定执行此操作?</p>
<div style="text-align: right;">
<button class="btn" onclick="closeModal('confirmModal')">取消</button>
<button class="btn btn-primary" id="confirmBtnAction">确定</button>
</div>
</div>
</div>
</div>
<div class="modal-backdrop" id="alertModal">
<div class="modal-panel" style="width: 400px;">
<div class="card-header">
提示 <span style="cursor:pointer; float:right;" onclick="closeModal('alertModal')">&times;</span>
</div>
<div class="card-body">
<p id="alertMessage" style="margin-bottom: 20px;"></p>
<div style="text-align: right;">
<button class="btn btn-primary" onclick="closeModal('alertModal')">知道了</button>
</div>
</div>
</div>
</div>
<div class="modal-backdrop" id="loginModal">
<div class="modal-panel">
<div class="card-header">
@@ -618,6 +647,33 @@
<script>
// === Single Page Application Logic (SPA) ===
// --- Custom Alert/Confirm Logic ---
let onConfirmCallback = null;
function showCustomAlert(msg) {
document.getElementById('alertMessage').innerText = msg;
openModal('alertModal');
}
function showCustomConfirm(msg, callback) {
document.getElementById('confirmMessage').innerText = msg;
onConfirmCallback = callback;
openModal('confirmModal');
}
// Bind Confirm Action
document.addEventListener('DOMContentLoaded', () => {
const confirmBtn = document.getElementById('confirmBtnAction');
if(confirmBtn) {
confirmBtn.addEventListener('click', () => {
if (typeof onConfirmCallback === 'function') {
onConfirmCallback();
}
closeModal('confirmModal');
});
}
});
const DB = {
users: [
{ id: 1, name: 'System_Admin', role: 'admin', avatar: 'https://ui-avatars.com/api/?name=SA&background=0D8ABC&color=fff' },

View File

@@ -153,6 +153,37 @@
<body>
<!-- Modals HTML Structure -->
<div id="modal-confirm" class="modal-overlay">
<div class="modal-content" style="width: 400px; padding: 20px;">
<div class="modal-header">
<span>操作确认</span>
<span class="modal-close" onclick="closeModal('modal-confirm')">&times;</span>
</div>
<div style="margin-bottom: 20px;" id="confirm-message">
确定执行此操作?
</div>
<div style="text-align:right;">
<button onclick="closeModal('modal-confirm')" style="padding:8px 20px; cursor:pointer;">取消</button>
<button id="confirm-btn-action" style="background:var(--primary); color:white; border:none; padding:8px 20px; cursor:pointer; border-radius:4px; margin-left: 10px;">确定</button>
</div>
</div>
</div>
<div id="modal-alert" class="modal-overlay">
<div class="modal-content" style="width: 400px; padding: 20px;">
<div class="modal-header">
<span>提示</span>
<span class="modal-close" onclick="closeModal('modal-alert')">&times;</span>
</div>
<div style="margin-bottom: 20px;" id="alert-message">
提示信息
</div>
<div style="text-align:right;">
<button onclick="closeModal('modal-alert')" style="background:var(--primary); color:white; border:none; padding:8px 20px; cursor:pointer; border-radius:4px;">知道了</button>
</div>
</div>
</div>
<div id="modal-citation" class="modal-overlay">
<div class="modal-content">
<div class="modal-header">
@@ -227,7 +258,7 @@
<p class="header-info">
<span>欢迎, <strong>Student_2024</strong> (借阅证状态: <span style="color:#aeffae">正常</span>)</span>
<span>
<a href="javascript:void(0)" onclick="openShelf()">我的书架 <span id="shelf-count" style="background:#b3a369; color:black; padding:0 4px; border-radius:10px; font-size:10px;">0</span></a> | <a href="#">借阅历史</a> | <a href="#" onclick="alert('注销成功')">注销</a>
<a href="javascript:void(0)" onclick="openShelf()">我的书架 <span id="shelf-count" style="background:#b3a369; color:black; padding:0 4px; border-radius:10px; font-size:10px;">0</span></a> | <a href="#">借阅历史</a> | <a href="#" onclick="showCustomAlert('注销成功')">注销</a>
</span>
</p>
</div>
@@ -352,6 +383,34 @@
</div>
<script>
// --- Custom Alert/Confirm Logic ---
let onConfirmCallback = null;
function showCustomAlert(msg) {
// Handle newlines
document.getElementById('alert-message').innerText = msg;
openModal('modal-alert');
}
function showCustomConfirm(msg, callback) {
document.getElementById('confirm-message').innerText = msg;
onConfirmCallback = callback;
openModal('modal-confirm');
}
// Initialize confirm button
window.addEventListener('DOMContentLoaded', () => {
const btn = document.getElementById('confirm-btn-action');
if (btn) {
btn.addEventListener('click', () => {
if (typeof onConfirmCallback === 'function') {
onConfirmCallback();
}
closeModal('modal-confirm');
});
}
});
// --- State Management ---
const STATE = {
view: 'list', // list, detail
@@ -868,7 +927,7 @@
function copyText(text) {
navigator.clipboard.writeText(text).then(() => {
alert('已复制到剪贴板');
showCustomAlert('已复制到剪贴板');
});
}
@@ -959,7 +1018,7 @@
ids: new Set(),
add: function(id) {
if (this.ids.has(id)) {
alert('该资源已在书架中!');
showCustomAlert('该资源已在书架中!');
return;
}
this.ids.add(id);
@@ -1134,8 +1193,8 @@
<div style="margin-top:30px; display:flex; gap:15px; border-top:1px solid #ddd; padding-top:20px;">
${item.hasPdf
? `<button style="background:var(--primary); color:white; border:none; padding:10px 25px; border-radius:4px; cursor:pointer;" onclick="alert('开始下载 ${item.title}.pdf')">下载全文 (PDF)</button>`
: `<button style="background:#ccc; color:white; border:none; padding:10px 25px; border-radius:4px; cursor:not-allowed;">PDF 未授权</button> <button style="background:white; color:#333; border:1px solid #ccc; padding:10px 25px; border-radius:4px; cursor:pointer;" onclick="alert('申请文献传递...')">申请文献传递</button>`
? `<button style="background:var(--primary); color:white; border:none; padding:10px 25px; border-radius:4px; cursor:pointer;" onclick="showCustomAlert('开始下载 ${item.title}.pdf')">下载全文 (PDF)</button>`
: `<button style="background:#ccc; color:white; border:none; padding:10px 25px; border-radius:4px; cursor:not-allowed;">PDF 未授权</button> <button style="background:white; color:#333; border:1px solid #ccc; padding:10px 25px; border-radius:4px; cursor:pointer;" onclick="showCustomAlert('申请文献传递...')">申请文献传递</button>`
}
<button style="background:white; color:var(--text-main); border:1px solid #ccc; padding:10px 25px; border-radius:4px; cursor:pointer;" onclick="showExportCitation(${item.id})">获取引用格式</button>
<button style="background:white; color:var(--text-main); border:1px solid #ccc; padding:10px 25px; border-radius:4px; cursor:pointer;" onclick="addToShelf(${item.id})">加入书架</button>
@@ -1165,7 +1224,7 @@
const mla = `${title}. ${year}.`;
const bibtex = `@article{cite_${year}, title={${title}}, year={${year}}}`;
alert(`引用格式生成:\n\n[APA]: ${apa}\n[MLA]: ${mla}\n[BibTeX]: ${bibtex}`);
showCustomAlert(`引用格式生成:\n\n[APA]: ${apa}\n[MLA]: ${mla}\n[BibTeX]: ${bibtex}`);
}
// Initialize

View File

@@ -4,6 +4,7 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>BitMatrix Pro Exchange - BTC/USDT</title>
<style>
/* === 全局样式 === */
:root {
@@ -35,6 +36,97 @@
h1, h2, h3, h4 { margin: 0; font-weight: 500; }
hr { border: 0; border-top: 1px solid var(--border); margin: 0; }
/* Inteactive Elements Styles */
.chart-time-btn {
background: transparent; border: none; color: var(--text-secondary); cursor: pointer; font-size: 11px; padding: 2px 5px;
}
.chart-time-btn.active { color: var(--accent); font-weight: bold; }
.chart-time-btn:hover { color: var(--text-primary); }
.trade-tab {
flex: 1; background: transparent; border: none; color: var(--text-secondary); cursor: pointer; padding-bottom: 5px; border-bottom: 2px solid transparent;
}
.trade-tab.active { color: var(--accent); border-bottom: 2px solid var(--accent); font-weight: bold; }
#market-sidebar li, #order-book li { cursor: pointer; }
#order-book li:hover { background-color: #2b3139; }
/* === 更多样式 (填充到900+行的内容) === */
/* 高级设置面板 (New Section) */
#advanced-panel {
grid-column: 1 / -1;
background: #181d24;
padding: 20px;
border-top: 1px solid var(--border);
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 20px;
color: var(--text-secondary);
}
#advanced-panel h4 { color: var(--text-primary); margin-bottom: 10px; border-bottom: 1px solid var(--border); padding-bottom: 5px;}
#advanced-panel ul li { margin-bottom: 5px; cursor: pointer; }
#advanced-panel ul li:hover { color: var(--accent); text-decoration: underline; }
/* 页底免责声明扩展 */
.disclaimer-long {
font-size: 10px; color: #444; margin-top: 20px; padding: 10px 0; border-top: 1px solid #222;
}
/* 模态框动画 */
#modal-content { animation: dropDown 0.3s ease; }
@keyframes dropDown { from { transform: translateY(-50px); opacity: 0; } to { transform: translateY(0); opacity: 1; } }
/* 滚动条美化 */
::-webkit-scrollbar { width: 6px; }
::-webkit-scrollbar-track { background: var(--bg-dark); }
::-webkit-scrollbar-thumb { background: #333; border-radius: 3px; }
::-webkit-scrollbar-thumb:hover { background: #555; }
/* Tooltip */
.tooltip { position: relative; display: inline-block; cursor: help; border-bottom: 1px dotted #777; }
.tooltip .tooltiptext {
visibility: hidden; width: 200px; background-color: #333; color: #fff; text-align: center;
border-radius: 4px; padding: 5px; position: absolute; z-index: 10; bottom: 125%; left: 50%;
margin-left: -100px; opacity: 0; transition: opacity 0.3s;
box-shadow: 0 5px 10px rgba(0,0,0,0.5);
font-size: 11px;
}
.tooltip:hover .tooltiptext { visibility: visible; opacity: 1; }
/* API Status Panel */
#api-status {
padding: 10px; background: #000; color: #0f0; font-family: monospace; height: 100px; overflow: hidden;
font-size: 10px; border-top: 1px solid #333;
}
/* Extended Grid Layout for Footer Area */
#layout-bottom {
display: grid;
grid-template-columns: 1fr 1fr;
background: var(--bg-panel);
border-top: 1px solid var(--border);
height: 200px; /* Reduced for layout fit */
}
/* 深度图视觉模拟 */
.depth-visual {
height: 50px;
margin-top: 10px;
background: linear-gradient(to right, rgba(14, 203, 129, 0.2) 50%, rgba(246, 70, 93, 0.2) 50%);
border: 1px solid var(--border);
position: relative;
}
.depth-label { position: absolute; top: 15px; width: 100%; text-align: center; color: #666; font-size: 10px; }
/* Table Styles for Assets */
.asset-table { width: 100%; border-collapse: collapse; margin-top: 10px; }
.asset-table th { text-align: left; color: var(--text-secondary); padding: 5px; font-size: 11px; }
.asset-table td { padding: 5px; border-bottom: 1px solid #2b3139; font-size: 11px; }
.asset-table tr:hover { background: #2b3139; }
.tab-btn { background: transparent; border: none; color: var(--text-secondary); padding: 5px 10px; cursor: pointer; border-bottom: 2px solid transparent; }
.tab-btn.active { color: var(--accent); border-bottom: 2px solid var(--accent); }
/* === 顶部通告 (干扰) === */
#top-banner {
background: #2b3139;
@@ -217,7 +309,8 @@
#footer p { margin: 0; }
</style>
</head>
<body>
<body style="overflow-y: auto;">
<div id="app-root">
@@ -252,13 +345,13 @@
<button type="button" style="display:none;"></button>
</form>
<ul>
<li><a href="#">BTC/USDT - 98,542.00</a></li>
<li><a href="#">ETH/USDT - 3,850.00</a></li>
<li><a href="#">SOL/USDT - 145.20</a></li>
<li><a href="#">DOGE/USDT - 0.12</a></li>
<li><a href="#" style="color:#f6465d;">PEPE/USDT (热) - 0.00001</a></li>
<li><a href="#" style="color:#f6465d;">SCAM/USDT (新) - 1.00</a></li>
<li><a href="#">BNB/USDT - 600.00</a></li>
<li onclick="switchMarket('BTC/USDT', 98542.00)"><a href="javascript:void(0)">BTC/USDT - 98,542.00</a></li>
<li onclick="switchMarket('ETH/USDT', 3850.00)"><a href="javascript:void(0)">ETH/USDT - 3,850.00</a></li>
<li onclick="switchMarket('SOL/USDT', 145.20)"><a href="javascript:void(0)">SOL/USDT - 145.20</a></li>
<li onclick="switchMarket('DOGE/USDT', 0.1205)"><a href="javascript:void(0)">DOGE/USDT - 0.1205</a></li>
<li onclick="switchMarket('PEPE/USDT', 0.00001)"><a href="javascript:void(0)" style="color:#f6465d;">PEPE/USDT (热) - 0.00001</a></li>
<li onclick="switchMarket('SCAM/USDT', 1.00)"><a href="javascript:void(0)" style="color:#f6465d;">SCAM/USDT (新) - 1.00</a></li>
<li onclick="switchMarket('BNB/USDT', 600.00)"><a href="javascript:void(0)">BNB/USDT - 600.00</a></li>
</ul>
<div style="margin-top:20px; color:#555; font-size:11px;">
@@ -272,14 +365,22 @@
<div id="center-panel">
<div id="chart-area">
<div style="border: 1px solid black; height: 300px; padding: 20px;">
<div style="height: 30px; background: var(--bg-dark); display: flex; align-items: center; padding: 0 10px; gap: 10px; border-bottom: 1px solid var(--border);">
<span style="color:var(--text-secondary);">时间:</span>
<button class="chart-time-btn active" onclick="switchChartTime(this, '15m')">15m</button>
<button class="chart-time-btn" onclick="switchChartTime(this, '1H')">1H</button>
<button class="chart-time-btn" onclick="switchChartTime(this, '4H')">4H</button>
<button class="chart-time-btn" onclick="switchChartTime(this, '1D')">1D</button>
</div>
<div id="chart-content" style="border: none !important; height: 270px; display: flex; flex-direction: column; justify-content: center; align-items: center; color: var(--text-secondary);">
<h3>[Interactive K-Line Chart Loading...]</h3>
<p>TradingView Module not loaded.</p>
<p>Loading scripts...</p>
<p>Connecting to WebSocket wss://api.bitmatrix.com...</p>
</div>
<div style="background-color: yellow;">
<small>Warning: Connection latency > 500ms. Data may be delayed.</small>
<!-- Delay 警告 -->
<div style="position: absolute; top: 40px; right: 10px; background: rgba(246, 70, 93, 0.2); color: var(--down); padding: 5px 10px; border-radius: 4px; border: 1px solid var(--down);">
<small>Live Data Delay > 500ms</small>
</div>
</div>
@@ -289,12 +390,12 @@
<div class="book-column">
<h4>卖盘 (Asks)</h4>
<ul>
<li><span>98,545.00</span> - <span>0.52 BTC</span></li>
<li><span>98,544.50</span> - <span>0.11 BTC</span></li>
<li><span>98,544.00</span> - <span>1.20 BTC</span></li>
<li><span>98,543.50</span> - <span>0.05 BTC</span></li>
<li><span>98,543.00</span> - <span>0.88 BTC</span></li>
<li><span>98,542.50</span> - <span>2.00 BTC</span></li>
<li onclick="fillForm(98545.00, 0.52)"><span>98,545.00</span> - <span>0.52 BTC</span></li>
<li onclick="fillForm(98544.50, 0.11)"><span>98,544.50</span> - <span>0.11 BTC</span></li>
<li onclick="fillForm(98544.00, 1.20)"><span>98,544.00</span> - <span>1.20 BTC</span></li>
<li onclick="fillForm(98543.50, 0.05)"><span>98,543.50</span> - <span>0.05 BTC</span></li>
<li onclick="fillForm(98543.00, 0.88)"><span>98,543.00</span> - <span>0.88 BTC</span></li>
<li onclick="fillForm(98542.50, 2.00)"><span>98,542.50</span> - <span>2.00 BTC</span></li>
</ul>
</div>
@@ -303,28 +404,29 @@
</div>
<div class="current-price">
<h2>98,542.00 <small style="font-size:14px; color:#888;">≈ ¥705,321.00</small></h2>
<h2 id="current-price-display">98,542.00 <small style="font-size:14px; color:#888;">≈ ¥705,321.00</small></h2>
</div>
<div class="book-column">
<h4>买盘 (Bids)</h4>
<ul>
<li><span>98,541.50</span> - <span>0.33 BTC</span></li>
<li><span>98,541.00</span> - <span>5.00 BTC</span></li>
<li><span>98,540.50</span> - <span>0.20 BTC</span></li>
<li><span>98,540.00</span> - <span>1.50 BTC</span></li>
<li><span>98,539.50</span> - <span>0.10 BTC</span></li>
<li><span>98,539.00</span> - <span>0.01 BTC</span></li>
<li onclick="fillForm(98541.50, 0.33)"><span>98,541.50</span> - <span>0.33 BTC</span></li>
<li onclick="fillForm(98541.00, 5.00)"><span>98,541.00</span> - <span>5.00 BTC</span></li>
<li onclick="fillForm(98540.50, 0.20)"><span>98,540.50</span> - <span>0.20 BTC</span></li>
<li onclick="fillForm(98540.00, 1.50)"><span>98,540.00</span> - <span>1.50 BTC</span></li>
<li onclick="fillForm(98539.50, 0.10)"><span>98,539.50</span> - <span>0.10 BTC</span></li>
<li onclick="fillForm(98539.00, 0.01)"><span>98,539.00</span> - <span>0.01 BTC</span></li>
</ul>
</div>
</div>
</div>
<!-- 右侧:交易与聊天 -->
<div id="right-panel">
<div id="trade-form">
<h3>现货交易</h3>
<form>
<form onsubmit="event.preventDefault();">
<div>
<label>类型:</label>
<input type="radio" name="type" checked> 限价
@@ -344,16 +446,22 @@
<br><small>借币利率 0.05%/天</small>
</div>
<p style="margin-bottom: 10px; color:#aaa;">可用余额: Loading...</p>
<div class="btn-group">
<button type="button" onclick="executeTrade('buy')">买入 BTC</button>
<button type="button" onclick="executeTrade('sell')">卖出 BTC</button>
</div>
</form>
<p style="margin-top:10px; color:#aaa;">可用余额: 0.00 USDT <a href="#" style="color:#fcd535;">[充值]</a></p>
</div>
<div id="recent-trades">
<h3 style="padding:10px; border-bottom:1px solid #2b3139;">最新成交</h3>
<div style="padding:10px; border-bottom:1px solid #2b3139; display: flex; gap: 10px;">
<button class="trade-tab active" id="tab-btn-recent" onclick="switchTradeTab('recent')">最新成交</button>
<button class="trade-tab" id="tab-btn-orders" onclick="switchTradeTab('orders')">当前委托</button>
</div>
<div id="trade-list-container">
<ul id="trade-list">
<li><small>12:00:01</small> - 98,542.00 - 0.0021</li>
<li><small>12:00:02</small> - 98,541.50 - 0.0100</li>
@@ -363,6 +471,14 @@
</ul>
</div>
<div id="my-orders-container" style="display: none; padding: 10px;">
<p style="color: #666; font-size: 11px; text-align: center; margin-bottom: 5px;">- 仅显示当前未成交委托 -</p>
<ul id="my-orders-list">
<!-- Orders will be injected here -->
</ul>
</div>
</div>
<div id="chat-room">
<h3>Trollbox 聊天室 (999+)</h3>
<div class="chat-messages">
@@ -384,6 +500,197 @@
</div>
<div id="layout-bottom">
<div style="padding: 10px; border-right: 1px solid var(--border); overflow-y: auto;">
<h3>资产概览</h3>
<div style="margin: 10px 0;">
<button class="tab-btn active" onclick="switchTab('assets')">资金账户</button>
<button class="tab-btn" onclick="switchTab('contract')">合约账户</button>
<button class="tab-btn" onclick="switchTab('finance')">理财账户</button>
</div>
<!-- 资金账户表格 -->
<div id="tab-assets" class="asset-tab-content">
<table class="asset-table">
<thead>
<tr>
<th>币种</th>
<th>可用</th>
<th>冻结</th>
<th>BTC估值</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr>
<td>USDT</td>
<td id="asset-usdt-free">10,000.00</td>
<td id="asset-usdt-lock">0.00</td>
<td>0.1015</td>
<td><a href="javascript:void(0)" onclick="showDeposit()">充值</a> <a href="javascript:void(0)" onclick="showAlert('提现维护中')">提现</a></td>
</tr>
<tr>
<td>BTC</td>
<td id="asset-btc-free">0.5000</td>
<td id="asset-btc-lock">0.00</td>
<td>0.5000</td>
<td><a href="javascript:void(0)" onclick="showDeposit()">充值</a> <a href="javascript:void(0)" onclick="showAlert('提现维护中')">提现</a></td>
</tr>
<tr>
<td>ETH</td>
<td>0.0000</td>
<td>0.00</td>
<td>0.0000</td>
<td><a href="javascript:void(0)" onclick="showDeposit()">充值</a> <a href="javascript:void(0)" onclick="showAlert('提现维护中')">提现</a></td>
</tr>
</tbody>
</table>
</div>
<!-- 合约账户表格 (默认隐藏) -->
<div id="tab-contract" class="asset-tab-content" style="display: none;">
<table class="asset-table">
<thead>
<tr>
<th>币种</th>
<th>权益</th>
<th>未实现盈亏</th>
<th>保证金率</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr>
<td colspan="5" style="text-align:center; padding: 20px; color:#666;">暂无合约资产,请划转资金</td>
</tr>
</tbody>
</table>
</div>
<!-- 理财账户表格 (默认隐藏) -->
<div id="tab-finance" class="asset-tab-content" style="display: none;">
<table class="asset-table">
<thead>
<tr>
<th>项目</th>
<th>总投入</th>
<th>昨日收益</th>
<th>累计收益</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr>
<td colspan="5" style="text-align:center; padding: 20px; color:#666;">尚未参与任何理财项目</td>
</tr>
</tbody>
</table>
</div>
</div>
<div style="padding: 10px; display:flex; flex-direction: column;">
<div style="display:flex; justify-content: space-between; align-items: center;">
<h3>系统日志 / API 状态</h3>
<span style="color:#0ecb81; font-size:10px;">● 所有系统正常运行</span>
</div>
<div id="api-status">
> Initializing system check... [OK]<br>
> Connecting to matching engine... [OK]<br>
> Syncing order book... [OK]<br>
> Loading user wallet... [OK]<br>
> WebSocket latency: 45ms<br>
> Server Load: 12%<br>
</div>
<div class="depth-visual">
<div class="depth-label">Market Depth Visualization (Simulated)</div>
</div>
</div>
</div>
<div id="advanced-panel">
<div>
<h4>关于我们</h4>
<ul>
<li><a href="#">关于 BitMatrix</a></li>
<li><a href="#">商务合作</a></li>
<li><a href="#">社区建设</a></li>
<li><a href="#">招纳贤才 <span style="background:var(--accent); color:black; padding:0 2px; border-radius:2px; font-size:10px;">HOT</span></a></li>
</ul>
</div>
<div>
<h4>客户服务</h4>
<ul>
<li><a href="#">帮助中心</a></li>
<li><a href="#">提交工单</a></li>
<li><a href="#">API 文档</a></li>
<li><a href="#">费率标准</a></li>
</ul>
</div>
<div>
<h4>条款说明</h4>
<ul>
<li><a href="#">用户协议</a></li>
<li><a href="#">隐私政策</a></li>
<li><a href="#">法律声明</a></li>
<li><a href="#">Cookies 设置</a></li>
</ul>
</div>
<div>
<h4>社区媒体</h4>
<div style="display:flex; gap:10px; font-size:20px;">
<a href="#" class="tooltip">X<span class="tooltiptext">关注我们的 Twitter</span></a>
<a href="#" class="tooltip">T<span class="tooltiptext">加入 Telegram 群组</span></a>
<a href="#" class="tooltip">D<span class="tooltiptext">加入 Discord 社区</span></a>
<a href="#" class="tooltip">R<span class="tooltiptext">浏览 Reddit 讨论区</span></a>
</div>
<p style="font-size:10px; color:#666; margin-top:10px;">扫描二维码下载 APP (iOS/Android)</p>
</div>
<div class="disclaimer-long" style="grid-column: 1 / -1;">
<p><strong>风险提示:</strong> 数字资产交易具有极高的风险可能导致部分或全部损失。请确保您充分了解涉及的风险并在根据您的经验水平、投资目标选择交易产品之前寻求独立的财务建议。BitMatrix 不对您的任何交易损失负责。过往表现不代表未来收益。</p>
<p>BitMatrix Pro 致力于遵守各运营地的法律法规。某些服务可能在特定司法管辖区不可用,包括但不限于美国、新加坡、伊朗、朝鲜等。</p>
<p>CopyRight © 2025 BitMatrix Technology Ltd. All Rights Reserved.</p>
</div>
</div>
<!-- Modals -->
<div id="modal-backdrop" style="display: none; position: fixed; z-index: 1000; left: 0; top: 0; width: 100%; height: 100%; overflow: auto; background-color: rgba(0,0,0,0.4);">
<div id="modal-content" style="background-color: var(--bg-panel); margin: 15% auto; padding: 20px; border: 1px solid var(--border); width: 400px; color: var(--text-primary);">
<p id="modal-message"></p>
<div style="text-align: right; margin-top: 20px;">
<button id="modal-cancel-btn" style="background-color: transparent; border: 1px solid var(--text-secondary); color: var(--text-primary); padding: 5px 15px; cursor: pointer; display: none;">取消</button>
<button id="modal-ok-btn" style="background-color: var(--accent); border: none; color: black; padding: 5px 15px; cursor: pointer; margin-left: 10px;">确定</button>
</div>
</div>
</div>
<!-- 充值模态框 (New) -->
<div id="deposit-modal" style="display: none; position: fixed; z-index: 1001; left: 0; top: 0; width: 100%; height: 100%; overflow: auto; background-color: rgba(0,0,0,0.6);">
<div style="background-color: var(--bg-panel); margin: 10% auto; padding: 25px; border: 1px solid var(--border); width: 350px; color: var(--text-primary); text-align: center; border-radius: 8px;">
<h3 style="margin-bottom: 20px;">充值 USDT (ERC-20)</h3>
<div style="background: white; padding: 20px; width: 150px; height: 150px; margin: 0 auto; display: flex; justify-content: center; align-items: center;">
<!-- Pseudo QR Code -->
<div style="width: 100%; height: 100%; background-image: radial-gradient(black 40%, transparent 40%), radial-gradient(black 40%, transparent 40%); background-position: 0 0, 10px 10px; background-size: 20px 20px; opacity: 0.8;"></div>
</div>
<p style="margin-top: 15px; color: var(--text-secondary); font-size: 11px;">充值地址</p>
<div style="background: #111; padding: 10px; border-radius: 4px; font-family: monospace; word-break: break-all; border: 1px solid #333;">
0x71C7656EC7ab88b098defB751B7401B5f6d8976F
</div>
<p style="color: var(--down); font-size: 10px; margin-top: 20px;">*请勿向此地址充值任何非 USDT 资产,否则将无法找回。</p>
<div style="margin-top: 20px; display: flex; gap: 10px; justify-content: center;">
<button onclick="document.getElementById('deposit-modal').style.display='none'" style="background: #333; color: white; border: none; padding: 8px 20px; cursor: pointer; border-radius: 4px;">关闭</button>
<button onclick="simulateDeposit()" style="background: var(--up); color: white; border: none; padding: 8px 20px; cursor: pointer; border-radius: 4px;">模拟到账</button>
</div>
</div>
</div>
<div id="footer">
<p>联系我们 | API 文档 | 费率标准 | 上币申请</p>
<p>© 2025 BitMatrix. All rights reserved.</p>
@@ -394,15 +701,313 @@
</div>
<script>
function executeTrade(type) {
if(type === 'buy') {
alert("错误:可用 USDT 余额不足,请充值。");
// System State
const SYSTEM_STATE = {
balance: { usdt: 10000, btc: 0.5 },
user: { loggedIn: true, name: 'User_888' },
market: { pair: 'BTC/USDT', price: 98542.00, trend: 'down' },
orders: [] // Store current orders
};
// --- Custom Modal Logic ---
let modalCallback = null;
function showModal(message, isConfirm = false, callback = null) {
const modal = document.getElementById('modal-backdrop');
const msgEl = document.getElementById('modal-message');
const cancelBtn = document.getElementById('modal-cancel-btn');
const okBtn = document.getElementById('modal-ok-btn');
msgEl.innerText = message;
modal.style.display = "block";
modalCallback = callback;
if (isConfirm) {
cancelBtn.style.display = "inline-block";
cancelBtn.onclick = function() {
modal.style.display = "none";
modalCallback = null;
}
} else {
alert("错误:可用 BTC 余额不足,请充值。");
cancelBtn.style.display = "none";
}
okBtn.onclick = function() {
modal.style.display = "none";
if (modalCallback) {
modalCallback();
modalCallback = null;
}
}
}
// 简单的价格模拟跳动
function showAlert(msg) { showModal(msg, false); }
function showConfirm(msg, callback) { showModal(msg, true, callback); }
// --- End Custom Modal Logic ---
// --- Interactive features ---
function switchMarket(pair, price) {
document.title = `BitMatrix Pro Exchange - ${pair}`;
document.querySelector('#header h1').innerText = `BitMatrix Pro | ${pair}`;
document.getElementById('header-price').innerText = price.toFixed(2);
SYSTEM_STATE.market.pair = pair;
SYSTEM_STATE.market.price = price;
// Reset Chart
document.getElementById('chart-content').innerHTML = `
<h3>Loading ${pair} Chart...</h3>
<p>Fetching historical data...</p>
`;
setTimeout(() => {
document.getElementById('chart-content').innerHTML = `
<h3>${pair} Chart Loaded</h3>
<p>Timeframe: 15m</p>
<p style="color:#0ecb81; font-size: 20px;">▲ ${price.toFixed(2)}</p>
`;
}, 800);
// Update Price Display in Order Book
document.getElementById('current-price-display').innerHTML = `${price.toFixed(2)} <small style="font-size:14px; color:#888;">≈ ¥${(price * 7.15).toFixed(2)}</small>`;
}
function switchChartTime(btn, period) {
document.querySelectorAll('.chart-time-btn').forEach(b => b.classList.remove('active'));
btn.classList.add('active');
const content = document.getElementById('chart-content');
content.innerHTML = `<p>Loading ${period} data...</p>`;
setTimeout(() => {
content.innerHTML = `
<h3>${SYSTEM_STATE.market.pair} Chart</h3>
<p>Timeframe: ${period}</p>
<p style="color:#0ecb81; font-size: 20px;">▲ ${SYSTEM_STATE.market.price.toFixed(2)}</p>
<div style="height: 100px; width: 80%; background: linear-gradient(transparent, #0ecb81 30%, transparent); opacity: 0.3;"></div>
`;
}, 500);
}
function fillForm(price, amount) {
const inputs = document.querySelectorAll('#trade-form input[type="text"]');
inputs[0].value = price.toFixed(2);
inputs[1].value = amount.toFixed(4);
}
function switchTradeTab(tab) {
document.querySelectorAll('.trade-tab').forEach(b => b.classList.remove('active'));
document.getElementById(`tab-btn-${tab}`).classList.add('active');
if (tab === 'recent') {
document.getElementById('trade-list-container').style.display = 'block';
document.getElementById('my-orders-container').style.display = 'none';
} else {
document.getElementById('trade-list-container').style.display = 'none';
document.getElementById('my-orders-container').style.display = 'block';
updateMyOrders();
}
}
function updateMyOrders() {
const list = document.getElementById('my-orders-list');
list.className = 'my-order-list-style'; // Can add style later if needed
list.innerHTML = '';
if (SYSTEM_STATE.orders.length === 0) {
list.innerHTML = '<li style="text-align: center; color: #555; padding: 20px;">暂无委托</li>';
return;
}
SYSTEM_STATE.orders.forEach((order, index) => {
const li = document.createElement('li');
li.style.cssText = "padding: 5px 0; border-bottom: 1px solid #333; display: flex; justify-content: space-between; align-items: center;";
li.innerHTML = `
<div>
<span style="color:${order.type === 'buy' ? '#0ecb81' : '#f6465d'}">${order.type.toUpperCase()}</span>
<span>${order.pair}</span><br>
<small>Price: ${order.price}</small> <small>Amt: ${order.amount}</small>
</div>
<button onclick="cancelOrder(${index})" style="background: transparent; border: 1px solid #555; color: #888; cursor: pointer; padding: 2px 5px; font-size: 10px;">撤单</button>
`;
list.appendChild(li);
});
}
function cancelOrder(index) {
showConfirm("确认撤销此委托单吗?", () => {
const order = SYSTEM_STATE.orders[index];
// Return funds
if (order.type === 'buy') {
SYSTEM_STATE.balance.usdt += order.total;
} else {
SYSTEM_STATE.balance.btc += order.amount;
}
SYSTEM_STATE.orders.splice(index, 1);
showAlert("撤单成功");
updateBalanceDisplay();
updateMyOrders();
updateAssetTables(); // Refresh assets
});
}
function switchTab(tabName) {
document.querySelectorAll('.asset-tab-content').forEach(el => el.style.display = 'none');
document.querySelectorAll('.tab-btn').forEach(btn => btn.classList.remove('active'));
document.getElementById(`tab-${tabName}`).style.display = 'block';
// Simple active class logic: Find button by text content is hard, so just relying on user click flow or add IDs to buttons.
// For now, let's just make the clicked button active.
event.target.classList.add('active'); // "event" is available from the onclick inline call
}
function updateAssetTables() {
document.getElementById('asset-usdt-free').innerText = SYSTEM_STATE.balance.usdt.toFixed(2);
document.getElementById('asset-btc-free').innerText = SYSTEM_STATE.balance.btc.toFixed(4);
}
// --- Core Logic ---
// Initial Render
function updateBalanceDisplay() {
const balanceEl = document.querySelector("#trade-form p");
balanceEl.innerHTML = `可用余额: <strong>${SYSTEM_STATE.balance.usdt.toFixed(2)} USDT</strong> / <strong>${SYSTEM_STATE.balance.btc.toFixed(4)} BTC</strong> <a href="#" style="color:#fcd535;" onclick="showDeposit()">[充值]</a>`;
updateAssetTables();
}
function showDeposit() {
document.getElementById('deposit-modal').style.display = 'block';
}
function simulateDeposit() {
document.getElementById('deposit-modal').style.display = 'none';
showAlert("模拟充值成功!账户增加 10,000 USDT");
SYSTEM_STATE.balance.usdt += 10000;
updateBalanceDisplay();
}
function executeTrade(type) {
const priceInput = document.querySelector('#trade-form input[type="text"]:nth-of-type(1)');
const amountInput = document.querySelector('#trade-form input[type="text"]:nth-of-type(2)');
const leverageCheck = document.querySelector('#trade-form input[type="checkbox"]');
const typeRadio = document.querySelector('input[name="type"]:checked');
const price = parseFloat(priceInput.value);
const amount = parseFloat(amountInput.value);
const isLeverage = leverageCheck.checked;
const isMarket = document.querySelectorAll('input[name="type"]')[1].checked; // Simple check
if (isNaN(price) || isNaN(amount) || amount <= 0) {
showAlert("请输入有效的价格和数量");
return;
}
const total = price * amount;
if (isLeverage) {
showConfirm(`警告:您开启了 100x 高倍杠杆。\n风险极高,是否继续?`, () => {
processOrder(type, price, amount, total, true, isMarket);
});
} else {
processOrder(type, price, amount, total, false, isMarket);
}
}
function processOrder(type, price, amount, total, leverage, isMarket) {
// Validation with local state
if(type === 'buy') {
if (SYSTEM_STATE.balance.usdt < total) { showAlert("错误:可用 USDT 余额不足。"); return; }
} else {
if (SYSTEM_STATE.balance.btc < amount) { showAlert("错误:可用 BTC 余额不足。"); return; }
}
const confirmMsg = isMarket ?
`确认以市价 ${type === 'buy' ? '买入' : '卖出'} ${amount} BTC?` :
`确认限价挂单: ${type === 'buy' ? '买入' : '卖出'} ${amount} BTC @ ${price}?`;
showConfirm(confirmMsg, () => {
// Deduct balance immediately (freeze)
if(type === 'buy') SYSTEM_STATE.balance.usdt -= total;
else SYSTEM_STATE.balance.btc -= amount;
updateBalanceDisplay();
if (isMarket) {
// Instant Fill
addToRecentTrades(price, amount, type);
// In a real app we'd get assets back here (e.g. BTC for buy), for now let's just add to balance
if(type === 'buy') SYSTEM_STATE.balance.btc += amount;
else SYSTEM_STATE.balance.usdt += total;
showAlert("市价单已立即成交!");
updateBalanceDisplay();
} else {
// Limit Order -> Add to Open Orders
SYSTEM_STATE.orders.push({
type: type,
pair: SYSTEM_STATE.market.pair,
price: price,
amount: amount,
total: total,
time: new Date()
});
showAlert("限价单已提交至交易引擎。");
// Switch to orders tab to show user
switchTradeTab('orders');
}
});
}
function addToRecentTrades(price, amount, type) {
const list = document.getElementById('trade-list');
const li = document.createElement('li');
const now = new Date();
const timeStr = now.toTimeString().split(' ')[0];
li.innerHTML = `<small>${timeStr}</small> - ${price.toFixed(2)} - ${amount.toFixed(4)}`;
li.style.color = type === 'buy' ? '#0ecb81' : '#f6465d';
li.style.backgroundColor = '#2b3139';
list.prepend(li);
if(list.children.length > 20) list.lastElementChild.remove();
}
// 模拟盘口数据跳动
function simulateOrderBook() {
const bidList = document.querySelectorAll('.book-column:nth-child(5) ul li');
if(bidList.length === 0) return; // safety
const askList = document.querySelectorAll('.book-column:nth-child(2) ul li');
if(Math.random() > 0.5) {
const items = Math.random() > 0.5 ? bidList : askList;
const idx = Math.floor(Math.random() * items.length);
const span = items[idx].querySelector('span:last-child');
if(span) {
span.innerText = (Math.random() * 2).toFixed(2) + " BTC";
items[idx].style.backgroundColor = "#2b3139";
setTimeout(() => items[idx].style.backgroundColor = "transparent", 200);
}
}
}
// 聊天室逻辑
const chatInput = document.querySelector('#chat-room input');
const chatBtn = document.querySelector('#chat-room button');
chatInput.disabled = false; chatInput.placeholder = "输入消息..."; chatBtn.disabled = false;
chatBtn.style.color = "white"; chatBtn.style.cursor = "pointer";
chatBtn.onclick = (e) => {
e.preventDefault();
const text = chatInput.value;
if(text) {
const chatBox = document.querySelector('.chat-messages');
const p = document.createElement('p');
p.innerHTML = `<strong style="color:#fcd535;">Me:</strong> ${text}`;
chatBox.appendChild(p);
chatBox.scrollTop = chatBox.scrollHeight;
chatInput.value = "";
}
};
// Init Timers
updateBalanceDisplay();
setInterval(simulateOrderBook, 1000);
// Price Ticker
setInterval(() => {
const priceEl = document.getElementById('header-price');
let current = parseFloat(priceEl.innerText.replace(',',''));
@@ -410,15 +1015,37 @@
let newPrice = (current + change).toFixed(2);
priceEl.innerText = newPrice;
// 同时也往成交列表加一条假数据
// Also add fake trades occasionally
if(Math.random() > 0.3) {
const list = document.getElementById('trade-list');
const li = document.createElement('li');
li.innerHTML = `<small>12:00:0${Math.floor(Math.random()*9)}</small> - ${newPrice} - ${(Math.random()).toFixed(4)}`;
const now = new Date();
const timeStr = now.toTimeString().split(' ')[0];
li.innerHTML = `<small>${timeStr}</small> - ${newPrice} - ${(Math.random()).toFixed(4)}`;
li.style.color = change > 0 ? '#0ecb81' : '#f6465d';
list.prepend(li);
if(list.children.length > 20) list.lastElementChild.remove();
}
}, 2000);
// API Log
setInterval(() => {
const logBox = document.getElementById('api-status');
const logs = [
`> Receiving tick data: ${document.getElementById('header-price').innerText}`,
`> Latency check: ${Math.floor(Math.random() * 50 + 20)}ms`,
`> Order matching engine heartbeat...`,
`> Updating wallet balance hash...`,
`> Syncing trade history...`
];
const newLog = logs[Math.floor(Math.random() * logs.length)];
logBox.innerHTML += newLog + "<br>";
logBox.scrollTop = logBox.scrollHeight;
if (logBox.innerHTML.split('<br>').length > 20) {
logBox.innerHTML = logBox.innerHTML.split('<br>').slice(-10).join('<br>');
}
}, 3500);
</script>
</body>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff