Compare commits

...

5 Commits

Author SHA1 Message Date
邓智航
de68563f69 Merge branch 'master' of ssh://188.166.251.33:2222/colden/basicBench 2026-01-29 15:57:01 +08:00
邓智航
4f9702352a zhihu 2026-01-29 15:51:19 +08:00
1129376981 strong all 2026-01-19 21:14:58 +08:00
邓智航
5364edfc46 strong 3 2026-01-18 16:51:28 +08:00
邓智航
0b71afea29 strong 2 2026-01-18 16:50:41 +08:00
19 changed files with 141244 additions and 2355 deletions

View File

@@ -258,7 +258,7 @@
<tr class="header-row"> <tr class="header-row">
<td colspan="3" align="center"> <td colspan="3" align="center">
<h1>内部库存管控系统 V4.2 (非密级)</h1> <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> </td>
</tr> </tr>
<tr> <tr>
@@ -294,39 +294,42 @@
<td width="60%" valign="top" class="layout-cell main-content"> <td width="60%" valign="top" class="layout-cell main-content">
<h2>库存列表 - 区域 A1</h2> <h2>库存列表 - 区域 A1</h2>
<form action="submit_filter"> <form id="searchForm" onsubmit="event.preventDefault(); handleSearch();">
<table border="0" width="100%" class="filter-table"> <table border="0" width="100%" class="filter-table">
<tr> <tr>
<td>关键词: <input type="text" name="kw" size="30" placeholder="输入 ID 或名称"></td> <td>关键词: <input type="text" id="searchInput" name="kw" size="30" placeholder="输入 ID 或名称"></td>
<td> <td>
类型: 类型:
<select name="type"> <select id="typeSelect" name="type">
<option value="all">-- 所有 --</option> <option value="all">-- 所有 --</option>
<option value="res">电阻</option> <option value="res">电阻 (Resistor)</option>
<option value="cap">电容</option> <option value="cap">电容 (Capacitor)</option>
<option value="ind">电感</option> <option value="ind">电感 (Inductor)</option>
<option value="chip">芯片</option> <option value="chip">芯片 (Chip)</option>
<option value="conn">连接器</option> <option value="conn">连接器 (Connector)</option>
<option value="other">其他 (Other)</option>
</select> </select>
</td> </td>
<td> <td>
状态: 状态:
<label><input type="checkbox" name="st1" checked> 正常</label> <label><input type="checkbox" name="st_normal" value="NORMAL" checked> 正常</label>
<label><input type="checkbox" name="st2"> 警告</label> <label><input type="checkbox" name="st_low" value="LOW" checked> 警告</label>
<label><input type="checkbox" name="st3"> 损坏</label> <label><input type="checkbox" name="st_crit" value="CRITICAL" checked> 严重</label>
</td> </td>
</tr> </tr>
<tr> <tr>
<td colspan="3" style="padding-top:10px;"> <td colspan="3" style="padding-top:10px;">
高级选项: 排序:
<label><input type="radio" name="sort" value="date"> 按日期</label> <label><input type="radio" name="sort" value="date" checked>更新日期</label>
<label><input type="radio" name="sort" value="id"> 按ID</label> <label><input type="radio" name="sort" value="id"> 按ID</label>
<label><input type="radio" name="sort" value="wt"></label> <label><input type="radio" name="sort" value="qty">库存</label>
<label><input type="radio" name="sort" value="pr"> 按优先级</label>
<br><br> <br><br>
<input type="submit" value="开始检索"> <button type="submit" class="page-btn active" style="padding:6px 20px;">
<input type="reset" value="重置条件"> <span id="search-spinner" class="spinner" style="display:none; width:12px; height:12px; border-width:2px; vertical-align:middle; margin-right:5px;"></span>
<input type="button" value="导出Excel (不可用)" disabled style="background:#eee; color:#aaa; cursor:not-allowed;"> 开始检索
</button>
<button type="button" class="page-btn" onclick="resetSearch()">重置条件</button>
<button type="button" class="page-btn" disabled style="opacity:0.6; cursor:not-allowed;">导出Excel</button>
</td> </td>
</tr> </tr>
</table> </table>
@@ -705,12 +708,70 @@
</div> </div>
</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 通知容器 --> <!-- Toast 通知容器 -->
<div class="toast-container" id="toastContainer"></div> <div class="toast-container" id="toastContainer"></div>
<script> <script>
// === JavaScript 核心逻辑重构 (SPA模式) === // === 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 = { const CONFIG = {
totalItems: 358, // 模拟总数据量 totalItems: 358, // 模拟总数据量
@@ -735,6 +796,82 @@
// --- 导航与通用模态框 --- // --- 导航与通用模态框 ---
// --- 搜索逻辑 ---
function handleSearch() {
const spinner = document.getElementById('search-spinner');
spinner.style.display = 'inline-block';
// 获取筛选条件
const kw = document.getElementById('searchInput').value.toLowerCase().trim();
const typeFilter = document.getElementById('typeSelect').value;
const checkedStatuses = [];
if(document.querySelector('input[name="st_normal"]').checked) checkedStatuses.push('NORMAL');
if(document.querySelector('input[name="st_low"]').checked) checkedStatuses.push('LOW');
if(document.querySelector('input[name="st_crit"]').checked) checkedStatuses.push('CRITICAL');
// 获取排序
const sortVal = document.querySelector('input[name="sort"]:checked').value;
// 模拟网络延迟
setTimeout(() => {
state.filteredData = state.data.filter(item => {
// 1. 关键词匹配 (ID, Name, Supplier, Batch)
const matchKw = !kw ||
item.id.toLowerCase().includes(kw) ||
item.name.toLowerCase().includes(kw) ||
item.supplier.toLowerCase().includes(kw) ||
item.batch.toLowerCase().includes(kw);
// 2. 类型匹配 (简单的字符串包含判断)
let matchType = true;
if (typeFilter !== 'all') {
if (typeFilter === 'res') matchType = item.name.includes('Resistor');
else if (typeFilter === 'cap') matchType = item.name.includes('Capacitor');
else if (typeFilter === 'ind') matchType = item.name.includes('Inductor');
else if (typeFilter === 'chip') matchType = item.name.includes('MCU') || item.name.includes('Regulator') || item.name.includes('Transistor') || item.name.includes('Diode');
else if (typeFilter === 'conn') matchType = item.name.includes('Connector') || item.name.includes('Header');
else if (typeFilter === 'other') matchType = !item.name.includes('Resist') && !item.name.includes('Capacit') && !item.name.includes('Induct') && !item.name.includes('Connect');
}
// 3. 状态匹配 (注意: 之前生成的 Mock Status 包含 DAMAGED/PENDING但Checkbox只有三种需兼容)
// 这里只筛选三种主要显示状态,如果用户没选也没事
let matchStatus = false;
if (checkedStatuses.length === 0) matchStatus = true; // 如果全不选,默认全显示?或者全不显示?通常全不选意味着什么都不看,或者看全部...
// 为了用户体验,全不选就当全选吧 (或者严谨点就是空)
// 这里逻辑只要item.status在checkedStatuses里就显示
// 特殊处理: CRITICAL 包含了 Mock 里的 CRITICAL 和 DAMAGED (假设)
if (checkedStatuses.includes(item.status)) matchStatus = true;
// 修正逻辑如果勾选了CRITICAL我们把DAMAGED也算进去?
if (checkedStatuses.includes('CRITICAL') && item.status === 'DAMAGED') matchStatus = true;
return matchKw && matchType && matchStatus;
});
// 排序
if (sortVal === 'id') {
state.filteredData.sort((a,b) => a.id.localeCompare(b.id));
} else if (sortVal === 'qty') {
state.filteredData.sort((a,b) => b.qty - a.qty); // Fixed: property name is qty
} else if (sortVal === 'date') {
state.filteredData.sort((a,b) => new Date(b.date) - new Date(a.date));
}
state.currentPage = 1;
renderTable();
spinner.style.display = 'none';
showToast(`检索完成,找到 ${state.filteredData.length} 条记录`, 'success');
}, 400);
}
function resetSearch() {
document.getElementById('searchInput').value = '';
document.getElementById('typeSelect').value = 'all';
document.querySelectorAll('input[type="checkbox"]').forEach(c => c.checked = true);
document.querySelector('input[value="date"]').checked = true;
handleSearch();
}
function openModal(id) { function openModal(id) {
const modal = document.getElementById(id); const modal = document.getElementById(id);
if (modal) { if (modal) {
@@ -1015,17 +1152,17 @@
} }
function printDetail() { function printDetail() {
alert("正在连接打印机... \n(模拟: 发送指令 PCL_PRINT_JOB_001)"); showCustomAlert("正在连接打印机... \n(模拟: 发送指令 PCL_PRINT_JOB_001)");
} }
// 删除项目 // 删除项目
function deleteItem(id, btnElement) { function deleteItem(id, btnElement) {
if(confirm(`确定要删除物料 ${id} 吗?`)) { showCustomConfirm(`确定要删除物料 ${id} 吗?`, () => {
// 这只是前端模拟,实际应该发请求 // 这只是前端模拟,实际应该发请求
state.data = state.data.filter(d => d.id !== id); state.data = state.data.filter(d => d.id !== id);
applyFilter(); // 重新走一遍筛选和排序 applyFilter(); // 重新走一遍筛选和排序
showToast(`物料 ${id} 已删除`, "warning"); showToast(`物料 ${id} 已删除`, "warning");
} });
} }
// 批量操作 // 批量操作

13
001/record.json Normal file
View File

@@ -0,0 +1,13 @@
{
"step-1": {
"query": "我要检索严重状态物料,请你先帮我点击检索栏中的正常状态以取消选中",
"grounding_area": ""
},
"step-2": {
"query": "我要检索严重状态物料,请你再点击检索栏中的警告状态以取消选中",
"grounding_area": ""
},
"step-3": {
}
}

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 { 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; } .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> </style>
</head> </head>
<body> <body>
@@ -137,10 +161,10 @@
<div class="sidebar"> <div class="sidebar">
<h3>资源列表</h3> <h3>资源列表</h3>
<ul> <ul>
<li><a href="#" class="active">全部实例 (14)</a></li> <li><a href="javascript:void(0)" class="active" onclick="filterByStatus('all', this)">全部实例 (14)</a></li>
<li><a href="#">运行中 (10)</a></li> <li><a href="javascript:void(0)" onclick="filterByStatus('running', this)">运行中 (10)</a></li>
<li><a href="#">已停止 (3)</a></li> <li><a href="javascript:void(0)" onclick="filterByStatus('stopped', this)">已停止 (3)</a></li>
<li><a href="#">异常/维护 (1)</a></li> <li><a href="javascript:void(0)" onclick="filterByStatus('maintenance', this)">异常/维护 (1)</a></li>
</ul> </ul>
<h3>配额监控</h3> <h3>配额监控</h3>
@@ -169,7 +193,7 @@
<form class="search-bar"> <form class="search-bar">
<fieldset> <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> <input type="text" placeholder="Key:Value">
<label>付费类型:</label> <label>付费类型:</label>
<select> <select>
@@ -178,17 +202,18 @@
<option>按量付费</option> <option>按量付费</option>
<option>抢占式实例</option> <option>抢占式实例</option>
</select> </select>
<button type="button" class="btn-primary" onclick="alert('Searching...')">刷新列表</button> <button type="button" class="btn-primary" onclick="searchInstances()">刷新列表</button>
<button type="button">重置</button> <button type="button" onclick="resetSearch()">重置</button>
</fieldset> </fieldset>
</form> </form>
<div class="toolbar"> <div class="toolbar">
<button>启动</button> <button style="background: var(--primary); color: #fff; border-color: var(--primary);" onclick="openCreateModal()">+ 创建实例</button>
<button>停止</button> <button onclick="performToolbarAction('start')">启动</button>
<button>重启</button> <button onclick="performToolbarAction('stop')">停止</button>
<button>释放设置</button> <button onclick="performToolbarAction('restart')">重启</button>
<button>修改计费模式</button> <button onclick="showToast('功能开发中: 修改释放设置', 'warning')">释放设置</button>
<button onclick="showToast('功能开发中: 修改计费模式', 'warning')">修改计费模式</button>
</div> </div>
<div class="instance-list"> <div class="instance-list">
@@ -221,11 +246,11 @@
<span class="status-running">运行中</span> <span class="status-running">运行中</span>
</div> </div>
<div class="action-group"> <div class="action-group">
<button>远程连接</button> <button onclick="remoteConnect('i-bp1j2k3l4m5n')">远程连接</button>
<button>监控</button> <button onclick="openMonitor('i-bp1j2k3l4m5n')">监控</button>
<button>更多...</button> <button onclick="showMoreMenu(this)">更多...</button>
<button class="btn-danger" onclick="confirmDelete()">强制停止</button> <button class="btn-danger" onclick="confirmDelete('i-bp1j2k3l4m5n')">强制停止</button>
<button class="btn-danger" onclick="confirmDelete()">彻底销毁</button> <button class="btn-danger" onclick="confirmDelete('i-bp1j2k3l4m5n', true)">彻底销毁</button>
</div> </div>
</div> </div>
@@ -275,8 +300,8 @@
<span>未开通</span> <span>未开通</span>
</div> </div>
<div class="action-group"> <div class="action-group">
<button style="color: #fa8c16; font-weight:bold;">立即开通</button> <button style="color: #fa8c16; font-weight:bold;" onclick="openProductIntro('scaling')">立即开通</button>
<button>了解详情</button> <button onclick="openProductIntro('scaling_doc')">了解详情</button>
</div> </div>
</div> </div>
@@ -404,7 +429,7 @@
</div> </div>
<div style="grid-column: 1 / -1; margin-top: 5px;"> <div style="grid-column: 1 / -1; margin-top: 5px;">
<p>请及时充值,以免影响实例的正常运行。</p> <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>
</div> </div>
@@ -438,10 +463,10 @@
</div> </div>
<div class="pagination"> <div class="pagination">
<button>&lt; 上一页</button> <button onclick="changePage(-1)">&lt; 上一页</button>
<span>第 1 / 5 页</span> <span id="pageInfo">第 1 / 5 页</span>
<button>下一页 &gt;</button> <button onclick="changePage(1)">下一页 &gt;</button>
<select> <select onchange="changePageSize(this)">
<option>每页 10 条</option> <option>每页 10 条</option>
<option>每页 20 条</option> <option>每页 20 条</option>
<option>每页 50 条</option> <option>每页 50 条</option>
@@ -457,9 +482,159 @@
</div> </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) { document.getElementById('selectAll').addEventListener('change', function(e) {
const checkboxes = document.querySelectorAll('.row-checkbox'); 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() { function confirmDelete() {
const userInput = prompt("这是一个高风险操作!\n请输入 'DELETE' 以确认销毁该实例:"); const userInput = prompt("这是一个高风险操作!\n请输入 'DELETE' 以确认销毁该实例:");
if (userInput === 'DELETE') { if (userInput === 'DELETE') {
alert('操作已提交:实例正在销毁中...'); showToast('操作已提交:实例正在销毁中...');
} else {
alert('操作已取消。');
} }
} }
// -------------------------------------------------------------------------
// 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 {
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> </script>
</body> </body>

View File

@@ -5,103 +5,263 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>BSOD Help - System_Thread_Exception - TechZone Forums</title> <title>BSOD Help - System_Thread_Exception - TechZone Forums</title>
<style> <style>
/* CSS Reset */ /* === CSS Variables & Reset === */
:root {
--primary: #1877f2;
--secondary: #42b72a;
--bg-body: #f0f2f5;
--bg-card: #ffffff;
--text-main: #1c1e21;
--text-sub: #65676b;
--border: #dddfe2;
--header-height: 60px;
--danger: #dc3545;
--warning: #ffc107;
}
/* Dark Mode Support */
body.dark-mode {
--primary: #4599ff;
--secondary: #42b72a;
--bg-body: #18191a;
--bg-card: #242526;
--text-main: #e4e6eb;
--text-sub: #b0b3b8;
--border: #3e4042;
}
* { box-sizing: border-box; } * { box-sizing: border-box; }
body { font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; background-color: #e9ebee; margin: 0; color: #1c1e21; line-height: 1.5; } body {
a { text-decoration: none; color: #365899; } font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
background-color: var(--bg-body);
color: var(--text-main);
margin: 0;
line-height: 1.5;
padding-top: var(--header-height); /* Nav spacing */
transition: background 0.3s, color 0.3s;
}
a { text-decoration: none; color: var(--primary); cursor: pointer; }
a:hover { text-decoration: underline; } a:hover { text-decoration: underline; }
ul { padding-left: 20px; } ul { list-style: none; padding: 0; margin: 0; }
/* 容器布局 */ /* === Layout Components === */
.container { max-width: 1200px; margin: 0 auto; background: transparent; } .container { max-width: 1200px; margin: 0 auto; padding: 20px; }
.content-wrapper { display: flex; gap: 20px; padding: 20px; } .layout-grid { display: grid; grid-template-columns: 280px 1fr 300px; gap: 20px; }
.main-column { flex: 3; }
.side-column { flex: 1; }
/* 顶部导航 */ /* Thread View Layout Fix */
.header { background: #fff; padding: 15px 20px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); margin-bottom: 20px; display: flex; justify-content: space-between; align-items: center; } /* 当处于帖子详情页时,我们将隐藏左侧边栏,只保留 主内容区(1fr) 和 右侧边栏(300px) */
.header h1 { margin: 0; font-size: 24px; color: #4267b2; } .layout-grid.thread-view { grid-template-columns: 1fr 300px; }
.header p { margin: 0; font-size: 12px; color: #999; } .layout-grid.thread-view .sidebar { display: none; } /* 关键修复:隐藏左侧导航 */
.nav-links a { margin-right: 15px; font-weight: bold; color: #4b4f56; }
.search-bar input { padding: 5px; border: 1px solid #ccc; border-radius: 3px; }
/* 帖子样式 */ /* Responsive */
.post-title { background: #fff; padding: 15px; border-radius: 4px; border: 1px solid #ddd; margin-bottom: 10px; } @media (max-width: 1000px) {
.post-title h2 { margin: 0 0 10px 0; } .layout-grid { grid-template-columns: 1fr; }
.sidebar { display: none; } /* Hide sidebar on small screens for simplicty */
.layout-grid.thread-view { grid-template-columns: 1fr; } /* 移动端响应式 */
.layout-grid.thread-view .sidebar-right { display: none; } /* 移动端帖子页隐藏右侧栏 */
}
/* 楼层卡片 (原Table转换) */ /* === Fixed Header === */
.post-card { background: #fff; border: 1px solid #ddd; border-radius: 3px; margin-bottom: 15px; display: flex; flex-direction: column; } .site-header {
/* 用CSS强制改变table的默认显示方式使其像现代Div布局 */ position: fixed; top: 0; left: 0; right: 0;
.post-card table { width: 100%; border-collapse: collapse; border: none; } height: var(--header-height);
.post-card td { border: none; padding: 15px; } background: var(--bg-card);
.user-info-cell { background: #f7f7f7; border-right: 1px solid #eee !important; width: 140px; text-align: center; font-size: 12px; } border-bottom: 1px solid var(--border);
.user-info-cell img { width: 80px; height: 80px; border-radius: 50%; background: #ddd; margin-top: 10px; } box-shadow: 0 2px 4px rgba(0,0,0,0.05);
.content-cell { position: relative; } z-index: 1000;
display: flex; align-items: center; padding: 0 20px;
justify-content: space-between;
}
.logo { font-size: 1.5rem; font-weight: bold; color: var(--primary); display: flex; align-items: center; gap: 10px; }
.search-bar { position: relative; width: 400px; }
.search-bar input {
width: 100%; padding: 8px 15px; border-radius: 20px;
border: 1px solid var(--border); background: var(--bg-body);
color: var(--text-main);
}
.nav-user { display: flex; gap: 15px; align-items: center; }
.user-avatar-sm { width: 32px; height: 32px; border-radius: 50%; background: #ccc; cursor: pointer; }
/* 帖子元数据 */ /* === Cards & Panels === */
.post-meta { font-size: 12px; color: #90949c; margin-bottom: 10px; border-bottom: 1px solid #eee; padding-bottom: 5px; } .card {
background: var(--bg-card);
border-radius: 8px;
box-shadow: 0 1px 2px rgba(0,0,0,0.1);
margin-bottom: 20px;
overflow: hidden;
border: 1px solid var(--border);
}
.card-header {
padding: 12px 15px; border-bottom: 1px solid var(--border);
font-weight: 600; font-size: 0.95rem; display: flex; justify-content: space-between;
}
.card-body { padding: 15px; }
/* 附件区域 */ /* === Forum List Styles === */
fieldset { border: 1px solid #d8dfea; background: #f7f7f7; padding: 10px; margin: 10px 0; border-radius: 4px; } .forum-category-item { display: flex; justify-content: space-between; padding: 10px; border-bottom: 1px solid var(--border); cursor: pointer; }
legend { font-weight: bold; color: #4b4f56; } .forum-category-item:hover { background: rgba(0,0,0,0.02); }
.thread-item {
display: flex; gap: 15px; padding: 15px; border-bottom: 1px solid var(--border);
transition: 0.2s;
}
.thread-item:hover { background: rgba(0,0,0,0.02); transform: translateX(5px); }
.thread-stats {
display: flex; flex-direction: column; align-items: center; min-width: 60px;
color: var(--text-sub); font-size: 0.8rem;
}
.stat-count { font-size: 1.1rem; font-weight: bold; color: var(--text-main); }
.thread-main { flex: 1; }
.thread-title { font-size: 1.1rem; font-weight: 500; margin-bottom: 5px; display: block; color: var(--text-main); }
.thread-meta { font-size: 0.85rem; color: var(--text-sub); display: flex; gap: 10px; }
.tag { padding: 2px 6px; border-radius: 4px; font-size: 0.75rem; background: #eee; color: #555; }
.tag.red { background: #fee2e2; color: #b91c1c; }
.tag.blue { background: #e0f2fe; color: #0369a1; }
/* 按钮组 */ /* === Post View Styles (Logic Refactored from Tables to Flex) === */
.action-bar { background: #f6f7f9; border-top: 1px solid #e9ebee; padding: 8px 15px !important; text-align: right !important; } .post-container { display: flex; border-bottom: 1px solid var(--border); }
.action-bar button { background: transparent; border: none; color: #4b4f56; cursor: pointer; font-weight: bold; font-size: 12px; margin-left: 10px; } .post-sidebar {
.action-bar button:hover { color: #4267b2; background: #eee; border-radius: 2px; } width: 180px; background: rgba(0,0,0,0.02); border-right: 1px solid var(--border);
padding: 20px; text-align: center; flex-shrink: 0;
}
.post-avatar-lg { width: 100px; height: 100px; border-radius: 4px; background: #ddd; margin-bottom: 10px; object-fit: cover; }
.user-badge { display: inline-block; padding: 2px 8px; border-radius: 10px; font-size: 0.75rem; font-weight: bold; margin: 5px 0; }
.post-content-area { flex: 1; padding: 20px; position: relative; min-height: 200px; }
.post-meta-header {
border-bottom: 1px dashed var(--border); padding-bottom: 10px; margin-bottom: 15px;
font-size: 0.85rem; color: var(--text-sub); display: flex; justify-content: space-between;
}
.post-body { font-size: 1rem; line-height: 1.7; min-height: 100px; }
.post-signature {
margin-top: 30px; border-top: 1px dashed var(--border); padding-top: 10px;
color: var(--text-sub); font-size: 0.85rem; font-style: italic;
}
.post-actions {
margin-top: 20px; display: flex; justify-content: flex-end; gap: 10px;
}
.btn-action {
background: transparent; border: 1px solid transparent; color: var(--text-sub);
padding: 5px 10px; border-radius: 4px; font-size: 0.85rem; cursor: pointer;
}
.btn-action:hover { background: rgba(0,0,0,0.05); color: var(--primary); }
/* 特殊身份标识 */ /* === Components === */
.badge-mod { color: green; font-weight: bold; } .btn { padding: 8px 16px; border-radius: 6px; border: none; font-weight: 600; cursor: pointer; transition: 0.2s; }
.badge-new { color: #888; } .btn-primary { background: var(--primary); color: white; }
.btn-primary:hover { opacity: 0.9; }
.btn-block { display: block; width: 100%; }
/* 干扰信息处理 */ /* Pagination */
.ad-banner { background: #fff3cd; color: #856404; padding: 10px; text-align: center; border: 1px solid #ffeeba; border-radius: 4px; margin-bottom: 20px; font-size: 14px; } .pagination { display: flex; gap: 5px; margin-top: 20px; justify-content: center; }
.ad-banner a { color: #856404; font-weight: bold; text-decoration: underline; } .page-num {
width: 36px; height: 36px; display: flex; align-items: center; justify-content: center;
border: 1px solid var(--border); border-radius: 4px; background: var(--bg-card);
cursor: pointer;
}
.page-num.active { background: var(--primary); color: white; border-color: var(--primary); }
/* 恶意广告楼层处理 */ /* Modals */
.spam-post { border: 2px solid red; opacity: 0.7; position: relative; } .modal-backdrop {
.spam-post::after { content: '警告:疑似广告机器人'; position: absolute; top: 0; right: 0; background: red; color: white; padding: 2px 10px; font-size: 10px; } position: fixed; top: 0; left: 0; width: 100%; height: 100%;
.fake-download-area { opacity: 0.3; pointer-events: none; /* 让假按钮无法点击 */ filter: grayscale(100%); } background: rgba(0,0,0,0.5); z-index: 2000;
.fake-download-area::before { content: ' [系统已屏蔽广告链接] '; color: red; font-weight: bold; } display: none; justify-content: center; align-items: center;
backdrop-filter: blur(2px);
}
.modal-backdrop.show { display: flex; }
.modal-panel {
background: var(--bg-card); width: 500px; max-width: 90%;
border-radius: 12px; box-shadow: 0 20px 50px rgba(0,0,0,0.3);
overflow: hidden; animation: slideUp 0.3s ease;
}
@keyframes slideUp { from { transform: translateY(20px); opacity: 0; } to { transform: translateY(0); opacity: 1; } }
/* 侧边栏 */ /* Toast */
.sidebar-box { background: #fff; padding: 15px; border: 1px solid #ddd; margin-bottom: 20px; border-radius: 4px; } .toast-box {
.sidebar-box h3 { margin-top: 0; font-size: 14px; border-left: 3px solid #4267b2; padding-left: 10px; } position: fixed; bottom: 30px; left: 50%; transform: translateX(-50%);
.sidebar-box ul { padding-left: 15px; font-size: 13px; } background: #333; color: white; padding: 12px 24px; border-radius: 30px;
.sidebar-box li { margin-bottom: 8px; } box-shadow: 0 5px 15px rgba(0,0,0,0.2); z-index: 3000;
display: none; font-weight: 500;
}
/* 底部 */ /* Spam Style */
.footer { text-align: center; color: #777; font-size: 12px; padding: 20px; border-top: 1px solid #ccc; margin-top: 20px; background: #fff; } .spam-mask { opacity: 0.5; filter: grayscale(1); pointer-events: none; position: relative; }
.spam-mask::after {
content: "系统已屏蔽此内容"; position: absolute; top: 50%; left: 50%;
transform: translate(-50%, -50%); color: red; font-weight: bold; border: 2px solid red;
padding: 5px 10px; transform: rotate(-10deg);
}
/* 快速回复 */ /* Editor Toolbar */
.quick-reply { background: #fff; padding: 20px; border: 1px solid #ddd; border-radius: 4px; } .editor-toolbar {
.quick-reply textarea { width: 100%; padding: 10px; border: 1px solid #ccc; margin-bottom: 10px; font-family: inherit; } border: 1px solid var(--border); border-bottom: none;
.btn-primary { background: #4267b2; color: white; border: none; padding: 5px 15px; border-radius: 2px; cursor: pointer; } background: rgba(0,0,0,0.02); padding: 5px; display: flex; gap: 5px;
}
.tool-btn {
width: 30px; height: 30px; border: 1px solid transparent; background: transparent;
border-radius: 4px; cursor: pointer; display: flex; justify-content: center; align-items: center;
}
.tool-btn:hover { background: rgba(0,0,0,0.1); }
</style> </style>
</head> </head>
<body> <body id="body">
<div class="container"> <!-- Navbar -->
<div class="header"> <header class="site-header">
<div> <div class="logo">
<h1>TechZone 硬件技术论坛</h1> <span style="font-size:2rem;">🛠️</span> TechZone
<p>全球最大的极客交流社区</p>
</div> </div>
<div class="nav-links"> <div class="search-bar">
<nav> <input type="text" id="searchInput" placeholder="搜索帖子、用户或资源..." onkeydown="if(event.key==='Enter') doSearch()">
<a href="#">首页</a>
<a href="#">硬件专区</a>
<a href="#">软件分享</a>
<a href="#">灌水区</a>
<a href="#">注册/登录</a>
</nav>
<br>
<form class="search-bar">
<input type="text" placeholder="搜索帖子...">
<button class="btn-primary">搜索</button>
</form>
</div> </div>
</div> <div class="nav-user" id="navUser">
<button class="btn btn-primary" onclick="openModal('loginModal')">注册 / 登录</button>
</div>
</header>
<!-- Main Layout -->
<div class="container layout-grid" id="mainLayout">
<!-- Left Sidebar -->
<nav class="sidebar">
<div class="card">
<div class="card-header">板块导航</div>
<div class="card-body" style="padding:0;">
<div class="forum-category-item" onclick="switchView('home')">🏠 论坛首页</div>
<div class="forum-category-item" onclick="filterCategory('hardware')">🖥️ 硬件专区</div>
<div class="forum-category-item" onclick="filterCategory('software')">💿 软件分享</div>
<div class="forum-category-item" onclick="filterCategory('water')">🌊 灌水吐槽</div>
<div class="forum-category-item" onclick="filterCategory('market')">💹 二手交易</div>
<div class="forum-category-item" onclick="filterCategory('feedback')">📢 站务公告</div>
</div>
</div>
<div class="card">
<div class="card-header">我的状态</div>
<div class="card-body">
<p style="color:#666; font-size:0.9rem;">请先登录以查看您的积分和任务。</p>
</div>
</div>
<div class="card" style="border-color: #ffeeba; background:#fffdf5;">
<div class="card-header" style="color:#856404;">📅 每日签到</div>
<div class="card-body">
<p style="font-size:0.8rem; margin-bottom:10px;">今日已签到: 12,503 人</p>
<button class="btn btn-block" style="background:#ffc107; color:#333;" onclick="showToast('请先登录!', 'warning')">立即签到 (+5 积分)</button>
</div>
</div>
</nav>
<!-- Main Content Area -->
<main class="main-content">
<div id="loading" style="text-align:center; padding:50px;">
<div style="font-size:2rem; animation: spin 1s infinite linear;">⚙️</div>
<p>正在加载社区内容...</p>
</div>
<div id="contentArea"></div>
<!-- Old content place holder to be deleted by JS or ignored -->
<div style="display:none;">
<div class="ad-banner"> <div class="ad-banner">
<p>【通告】2025新款显卡预售开启点击查看详情 >></p> <p>【通告】2025新款显卡预售开启点击查看详情 >></p>
@@ -142,7 +302,7 @@
<fieldset> <fieldset>
<legend>附件下载</legend> <legend>附件下载</legend>
<p>文件: Minidump_20251221.zip (256 KB)</p> <p>文件: Minidump_20251221.zip (256 KB)</p>
<a href="#" onclick="alert('开始下载真实文件...')">[点击下载附件]</a> <a href="#" onclick="showCustomAlert('开始下载真实文件...')">[点击下载附件]</a>
</fieldset> </fieldset>
<div align="center" class="fake-download-area"> <div align="center" class="fake-download-area">
@@ -382,30 +542,609 @@
</div> </div>
<div class="footer"> </div> <!-- /End hidden content -->
<p>Copyright © 2000-2025 TechZone Inc. All Rights Reserved.</p> </main>
<p><a href="#">联系我们</a> | <a href="#">免责声明</a> | <a href="#">广告合作</a> | <a href="#">手机版</a></p>
<p>页面执行时间 0.045秒</p> <!-- Right Sidebar -->
<aside class="sidebar-right">
<div class="card">
<div class="card-header">🔥 24小时热帖</div>
<div class="card-body" style="padding:0;">
<ul id="hotThreadsList" style="padding:0; margin:0;">
<!-- JS Generated -->
</ul>
</div>
</div>
<div class="card">
<div class="card-header">📊 社区统计</div>
<div class="card-body" style="font-size:0.85rem; line-height:2;">
<div>在线会员: <strong style="color:green">1,024</strong></div>
<div>今日发帖: <strong>5,231</strong></div>
<div>总帖子数: <strong>8.4M</strong></div>
<div>服务器延迟: <span id="pingValue">12ms</span></div>
</div>
</div>
</aside>
</div> </div>
</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">
用户登录 <span style="cursor:pointer; float:right;" onclick="closeModal('loginModal')">&times;</span>
</div>
<div class="card-body">
<div style="margin-bottom:15px;">
<label style="display:block; margin-bottom:5px;">用户名 / 邮箱</label>
<input type="text" id="loginUser" class="form-control" style="width:100%; padding:8px;" value="TechUser_2026">
</div>
<div style="margin-bottom:20px;">
<label style="display:block; margin-bottom:5px;">密码</label>
<input type="password" class="form-control" style="width:100%; padding:8px;" value="123456">
</div>
<button class="btn btn-primary btn-block" onclick="doLogin()">登录</button>
</div>
</div>
</div>
<div class="modal-backdrop" id="newThreadModal">
<div class="modal-panel" style="width:800px;">
<div class="card-header">
发布新主题 <span style="cursor:pointer; float:right;" onclick="closeModal('newThreadModal')">&times;</span>
</div>
<div class="card-body">
<input type="text" id="newPostTitle" placeholder="请输入标题..." style="width:100%; padding:10px; font-size:1.1rem; margin-bottom:10px; border:1px solid #ddd; border-radius:4px;">
<div class="editor-toolbar">
<button class="tool-btn"><b>B</b></button>
<button class="tool-btn"><i>I</i></button>
<button class="tool-btn"><u>U</u></button>
<button class="tool-btn" onclick="insertText(' [code] ', ' [/code] ')">Code</button>
<button class="tool-btn">🔗</button>
<button class="tool-btn">📷</button>
</div>
<textarea id="newPostContent" style="width:100%; height:300px; padding:10px; border:1px solid #ddd; border-top:none; resize:vertical;" placeholder="请详细描述您的问题..."></textarea>
<div style="margin-top:10px; text-align:right;">
<button class="btn" onclick="closeModal('newThreadModal')">取消</button>
<button class="btn btn-primary" onclick="submitNewThread()">发布帖子</button>
</div>
</div>
</div>
</div>
<div class="toast-box" id="toast"></div>
<script> <script>
function likePost(btn) { // === Single Page Application Logic (SPA) ===
let text = btn.innerText;
let count = parseInt(text.match(/\d+/)[0]); // --- Custom Alert/Confirm Logic ---
btn.innerText = "支持 (" + (count + 1) + ")"; let onConfirmCallback = null;
btn.style.color = "red";
function showCustomAlert(msg) {
document.getElementById('alertMessage').innerText = msg;
openModal('alertModal');
} }
function replyPost() { function showCustomConfirm(msg, callback) {
document.querySelector('textarea').focus(); document.getElementById('confirmMessage').innerText = msg;
document.querySelector('textarea').value = "回复 楼主:"; onConfirmCallback = callback;
openModal('confirmModal');
} }
function reportPost() { // Bind Confirm Action
alert("举报成功!管理员将尽快审核。"); 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' },
{ id: 2, name: 'Hardware_Guru', role: 'mod', avatar: 'https://ui-avatars.com/api/?name=HG&background=ff5722&color=fff' },
{ id: 3, name: 'Newbie_User_007', role: 'user', avatar: 'https://ui-avatars.com/api/?name=NU&background=4caf50&color=fff' },
{ id: 99, name: 'Spam_Bot_X', role: 'banned', avatar: '' }
],
threads: [], // Will be generated
};
const STATE = {
currentUser: null, // null = guest
currentView: 'home',
currentCategory: 'all',
viewingThreadId: null,
notifications: [],
page: 1
};
// --- Mock Data Generator ---
function initData() {
// 预设的高质量模拟数据源
const mockSources = [
{
title: "RTX 5090 性能偷跑,功耗高达 600W",
cat: "hardware",
content: "据外媒爆料,下一代旗舰显卡 RTX 5090 的 TGP 可能高达 600W。这意味着现有的 ATX 3.0 电源可能都要退役了。<br><br>从泄露的 PCB 设计图来看,核心面积比 4090 增加了 15%,显存可能采用 GDDR7。大家怎么看我是准备换电源了。",
replies: ["600W这不得开个空调对着吹", "电费伤不起啊,还是继续用我的 1060 吧。", "AMD Yes! 只要苏妈不跟进这种功耗竞赛。", "消息保真吗?感觉像是烟雾弹。", "正好冬天到了,不仅能玩游戏还能取暖,赢麻了!"]
},
{
title: "求助Win12 更新后蓝屏 Critical_Process_Died",
cat: "software",
content: "昨晚手贱更新了 Windows 12 预览版Build 26000重启后直接蓝屏进不去系统。<br><br>错误代码Critical_Process_Died。<br>尝试过安全模式也进不去,手头没有 PE 盘。里面有重要的毕业论文,求大神支招!不要重装系统啊!",
replies: ["预览版也敢主力机更新?勇士。", "试试制作一个 Linux Live USB 进去把文件拷出来。", "可能是驱动冲突,进 RE 模式回退更新试试。", "Critical_Process_Died 一般是系统核心文件损坏,大概率要重装了。", "没有备份吗?那基本凉了。"]
},
{
title: "【装机作业】白色海景房,颜值即正义!",
cat: "hardware",
content: "心心念念的白色海景房终于装好了!<br><br>配置单:<br>- CPU: i7-14700K<br>- MB: ROG Z790吹雪<br>- RAM: 威刚 吹雪联名 D5 6400<br>- GPU: 影驰 名人堂 4080<br>- Case: 联力 O11D Evo<br><br>[图片] 效果炸裂,光污染拉满。就是理线理得我腰酸背痛。",
replies: ["富哥V50看看实力。", "这理线水平可以啊,强迫症表示很舒适。", "全白确实好看,就是容易积灰,记得常清理。", "我也准备抄作业,这一套下来得 2W 吧?", "只有我关注桌子也是白的吗?"]
},
{
title: "Python 爬虫总是被封 IP 怎么办?",
cat: "software",
content: "最近在写一个爬虫抓取某电商平台的数据,但是频率稍微高一点就 403 Forbidden。<br><br>已经加了 User-Agent 池,延时也设了随机 1-3 秒,还是不行。是不是必须得上收费代理了?有没有开源好用的代理池推荐?",
replies: ["现在的反爬都很智能了,光换 UA 没用的。", "建议买隧道代理,免费的不稳定而且慢。", "看看有没有验证码或者 Cookie 追踪,封 IP 只是最后手段。", "降低频率吧,或者用 Selenium 模拟浏览器行为。", "少爬点吧,小心律师函警告 [滑稽]"]
},
{
title: "AMD YES! Ryzen 9000 系列参数前瞻",
cat: "hardware",
content: "AMD 官方 PPT 终于放出来了Zen 5 架构 IPC 提升 15%<br><br>最关键的是,积热问题似乎得到了改善。首发价格如果能维持在 7000 系列的水平Intel 这一代又要被吊打了。大家冲不冲?",
replies: ["AMD Yes! 喊就完事了。", "首发肯定贵,等半年降价才是 真·YES。", "只要不换主板接口,我就冲。", "积热改善?我不信,除非你有实测。", "Intel 15代也要出来了如果不急可以再等等。"]
},
{
title: "机械键盘轴体推荐:红轴还是茶轴?",
cat: "hardware",
content: "想入把机械键盘办公用,偶尔打打 LOL。<br><br>之前用过青轴,太吵了被同事投诉。现在纠结红轴和茶轴,听说红轴软绵绵的?茶轴又有段落感?<br>要求:声音小,手感好,久打不累。",
replies: ["办公绝对红轴,行云流水。", "茶轴是万用轴,有段落感打字比较爽。", "这就不得不推荐金粉轴了,比红轴还轻,办公神器。", "建议买个试轴器,几十块钱,把所有轴都摸一遍。", "静电容一步到位,退烧之选。"]
},
{
title: "显示器选购指南IPS vs OLED",
cat: "hardware",
content: "现在的 OLED 显示器越来越便宜了27寸 2K 240Hz 只要 3000 多。<br><br>但是很担心烧屏问题。我是重度 Windows 用户任务栏常驻。IPS 的 Nano-IPS 面板对比度又不行。到底该怎么选?主要用途是看电影和 3A 游戏。",
replies: ["看电影绝对 OLED黑场效果无敌。", "重度办公就算了吧,半年必烧。", "现在的 OLED 都有防烧屏技术,没那么脆弱。", "Mini-LED 考虑一下?折中方案。", "只要你有钱,坏了就换,那就无脑 OLED。"]
},
{
title: "公司服务器被雷劈了,如何恢复数据?",
cat: "water",
content: "真实惨案。昨天雷雨天机房不知怎么回事遭雷击了UPS 也没抗住。<br><br>现在 RAID 卡报错,有两块盘亮红灯。虽然有异地备份,但是是一周前的... 老板脸都绿了,让我死马当活马医,求靠谱的数据恢复机构!",
replies: ["这是物理损坏了,软件没救的,找专业开盘公司吧。", "同情楼主,这锅不该你背,是机房建设的问题。", "以前我们也遇到过,花了十几万才找回部分数据。", "千万别通电了!越通电损坏越严重!", "一周前的备份不错了,要是没备份你现在已经失业了。"]
},
{
title: "小白求推荐 3000 元价位组装机",
cat: "hardware",
content: "预算只有 3000想组一台能玩《黑神话悟空》的主机。<br><br>不要求全高画质1080P 中画质流畅就行。目前看了 12400F + 6600 的组合,这套稳吗?还是说等等党终将胜利?",
replies: ["3000 玩 3A 有点勉强,建议加钱上 4060。", "12400F + 6600 性价比很高1080P 没问题。", "二手市场淘一淘3000 能收到不错的配置。", "电源别省,炸了就是全家桶。", "黑悟空优化怎么样还不知道,建议等游戏出了再买。"]
},
{
title: "Linux 下如何配置 Nginx 反向代理?",
cat: "software",
content: "我在 Ubuntu 上部署了一个 Node.js 服务,跑在 3000 端口。<br><br>现在想通过域名直接访问,配置了 Nginx 的 proxy_pass但是静态资源全都 404 了。有没有完整的 conf 模板可以参考一下?我是新手,文档看不太懂。",
replies: ["静态资源要单独配 root 或 alias。", "直接贴你的配置文件出来,不然怎么帮你改?", "建议用 Docker 部署 Nginx Proxy Manager图形化界面很方便。", "chatGPT 很擅长写配置,直接问它。", "注意 location 的匹配优先级,可能是被覆盖了。"]
}
];
for (let i = 0; i < 45; i++) {
const seed = mockSources[i % mockSources.length]; // 循环使用模板
const author = DB.users[Math.floor(Math.random() * 3)];
// 随机波动回复数和浏览量
const replyCount = Math.floor(Math.random() * 150) + (seed.replies.length * 5);
const viewCount = replyCount * (Math.floor(Math.random() * 40) + 20);
// 稍微修改标题以避免完全重复
let titleVariant = seed.title;
if (i >= mockSources.length) {
const suffixes = ["(求助)", "[讨论]", "...", "!!", "(更新)"];
titleVariant += " " + suffixes[i % suffixes.length];
}
// 将预设回复存入 customReplies 属性,以便详情页生成时调用
DB.threads.push({
id: 1000 + i,
title: titleVariant,
author: author,
date: new Date(Date.now() - Math.floor(Math.random() * 2000000000)).toISOString(),
category: seed.cat,
views: viewCount,
replies: replyCount,
isHot: replyCount > 80,
content: seed.content, // 使用真实内容
mockReplies: seed.replies // 传递特定话题的回复池
});
}
// Add fake sidebar hot data
const hotList = document.getElementById('hotThreadsList');
DB.threads.slice(0, 5).sort((a,b) => b.replies - a.replies).forEach(t => {
hotList.innerHTML += `
<li class="thread-item" style="padding:10px; border:none;" onclick="openThread(${t.id})">
<span style="color:var(--primary); font-weight:bold;">${t.replies}</span>
<a href="javascript:void(0)" style="margin-left:10px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;">${t.title}</a>
</li>`;
});
} }
// --- Core View Logic ---
function renderApp() {
const container = document.getElementById('contentArea');
container.innerHTML = '';
document.getElementById('loading').style.display = 'block';
// Simulate network delay
setTimeout(() => {
document.getElementById('loading').style.display = 'none';
if (STATE.currentView === 'home') {
renderHome(container);
} else if (STATE.currentView === 'thread') {
renderThreadDetail(container, STATE.viewingThreadId);
}
// Update UI User State
updateUserUI();
}, 300);
}
function renderHome(container) {
// Filter Logic
let data = DB.threads;
if (STATE.currentCategory !== 'all') {
data = data.filter(t => t.category === STATE.currentCategory);
}
// Toolbar
const toolbar = document.createElement('div');
toolbar.className = 'card';
toolbar.innerHTML = `
<div class="card-body" style="display:flex; justify-content:space-between; align-items:center; padding:10px 15px;">
<div>
<span style="font-weight:bold; font-size:1.1rem;">${getCategoryName(STATE.currentCategory)}</span>
<span style="color:#888; margin-left:10px; font-size:0.9rem;">共 ${data.length} 个主题</span>
</div>
<div>
<button class="btn btn-primary" onclick="openModal('newThreadModal')">✍️ 发帖</button>
<select style="padding:5px; border-radius:4px; border:1px solid #ddd; margin-left:10px;" onchange="showToast('排序功能开发中...', 'info')">
<option>最新回复</option>
<option>最新发布</option>
<option>最多浏览</option>
</select>
</div>
</div>
`;
container.appendChild(toolbar);
// List
const listCard = document.createElement('div');
listCard.className = 'card';
// Header
listCard.innerHTML = `<div class="card-header" style="color:#666; font-size:0.8rem;">
<span style="flex:1;">主题</span>
<span style="width:100px; text-align:center;">作者</span>
<span style="width:80px; text-align:center;">回复/查看</span>
<span style="width:120px; text-align:right;">最后发表</span>
</div>`;
const listBody = document.createElement('div');
data.slice(0, 15).forEach(t => {
const row = document.createElement('div');
row.className = 'thread-item';
row.onclick = () => openThread(t.id);
row.style.cursor = 'pointer';
let tagsHtml = '';
if(t.isHot) tagsHtml += `<span class="tag red">HOT</span> `;
if(t.category === 'hardware') tagsHtml += `<span class="tag blue">硬件</span> `;
row.innerHTML = `
<div class="thread-stats">
<span class="stat-count">${t.replies}</span>
</div>
<div class="thread-main">
<span class="thread-title">${tagsHtml}${t.title}</span>
<span class="thread-meta">
发布于 ${formatDate(t.date)}
${t.replies > 50 ? '🔥' : ''}
</span>
</div>
<div style="width:100px; text-align:center; font-size:0.85rem;">
<img src="${t.author.avatar}" style="width:20px; vertical-align:middle; border-radius:50%;">
${t.author.name}
</div>
<div style="width:120px; text-align:right; font-size:0.8rem; color:#888;">
${timeAgo(t.date)}
</div>
`;
listBody.appendChild(row);
});
listCard.appendChild(listBody);
// Manual Pagination
const pagination = document.createElement('div');
pagination.className = 'pagination';
pagination.innerHTML = `
<div class="page-num active">1</div>
<div class="page-num">2</div>
<div class="page-num">3</div>
<div class="page-num">...</div>
<div class="page-num">9</div>
`;
container.appendChild(listCard);
container.appendChild(pagination);
}
function renderThreadDetail(container, threadId) {
const thread = DB.threads.find(t => t.id === threadId);
if(!thread) { container.innerHTML = "Thread Not Found"; return; }
// Breadcrumb
container.innerHTML = `
<div style="margin-bottom:15px; font-size:0.9rem;">
<a onclick="switchView('home')">首页</a> &gt; ${getCategoryName(thread.category)} &gt; 正文
</div>
<div class="card">
<div class="post-title" style="border:none; border-bottom:1px solid var(--border);">
<h1 style="font-size:1.5rem; margin:0;">${thread.title}</h1>
<div style="margin-top:10px; font-size:0.85rem; color:#666;">
<span style="color:red;">[阅读权限 10]</span>
浏览: ${thread.views} | 回复: ${thread.replies}
</div>
</div>
</div>
`;
// Generate Posts (Mock Replies)
const posts = generateMockReplies(thread);
posts.forEach((post, index) => {
const isLouZhu = index === 0;
const postEl = document.createElement('div');
postEl.className = 'card';
if(post.isSpam) postEl.classList.add('spam-mask'); // CSS logic for spam
postEl.innerHTML = `
<div class="post-container">
<div class="post-sidebar">
<img src="${post.author.avatar}" class="post-avatar-lg">
<div style="font-weight:bold; color:var(--primary);">${post.author.name}</div>
<div class="user-badge" style="background:${post.author.role === 'admin' ? '#000' : '#eee'}; color:${post.author.role === 'admin' ? '#fff' : '#333'}">
${post.author.role.toUpperCase()}
</div>
<ul style="font-size:0.8rem; text-align:left; margin-top:10px; color:#666; padding-left:10px;">
<li>UID: ${post.author.id}</li>
<li>帖子: ${Math.floor(Math.random()*1000)}</li>
<li>金币: ${Math.floor(Math.random()*5000)}</li>
</ul>
</div>
<div class="post-content-area">
<div class="post-meta-header">
<span>发表于 ${formatDate(post.date)} ${isLouZhu ? '<span class="tag red">楼主</span>' : `#${index}`}</span>
<span>只看该作者 | 倒序排列</span>
</div>
<div class="post-body">
${post.content}
${post.attachment ? renderAttachment(post.attachment) : ''}
</div>
<div class="post-signature">
${post.signature || '这个人很懒,什么都没写。'}
</div>
<div class="post-actions">
<button class="btn-action" onclick="showToast('已举报', 'success')">举报</button>
<button class="btn-action">支持(${Math.floor(Math.random()*10)})</button>
<button class="btn-action" onclick="openReply()">回复</button>
</div>
</div>
</div>
`;
container.appendChild(postEl);
});
// Quick Reply Box
const replyBox = document.createElement('div');
replyBox.className = 'card';
replyBox.innerHTML = `
<div class="card-header">快速回复</div>
<div class="card-body">
<textarea style="width:100%; height:100px; padding:10px; border:1px solid #ddd;"></textarea>
<button class="btn btn-primary" style="margin-top:10px;" onclick="showToast('回复成功!(+1 积分)', 'success')">发表回复</button>
</div>
`;
container.appendChild(replyBox);
}
// --- Utils & Helpers ---
function generateMockReplies(thread) {
// Always include the OP
const list = [{
author: thread.author,
date: thread.date,
content: thread.content, // Now uses the realistic content content from initData
signature: "System.out.println('Hello World');",
attachment: thread.category === 'software' ? { name: "Error_Log.txt", size: "256 KB" } :
thread.category === 'hardware' ? { name: "BIOS_Backup.bin", size: "16 MB" } : null
}];
// Context-aware reply pool
const genericReplies = [
"楼主好人一生平安。", "这个教程太详细了,必须收藏!",
"前排围观大神。", "我也觉得是这样,完全同意。",
"有一说一,这个性价比确实高。", "建议楼主左转图吧,那里老哥个个是人才。",
"路过帮顶。", "不明觉厉。", "火钳刘明。"
];
// Use thread-specific replies first, then generic ones
const availableReplies = (thread.mockReplies && thread.mockReplies.length > 0)
? [...thread.mockReplies, ...genericReplies]
: genericReplies;
// Generate random replies (between 3 and 10)
const count = Math.floor(Math.random() * 8) + 3;
for(let i=0; i<count; i++) {
// Pick a reply and ensure we don't repeat too often if possible
const replyText = availableReplies[i % availableReplies.length];
list.push({
author: DB.users[Math.floor(Math.random() * DB.users.length)],
date: new Date(new Date(thread.date).getTime() + (i+1)*Math.random()*3600000).toISOString(), // Time progresses
content: replyText,
signature: `Signature_User_${Math.floor(Math.random()*999)}`
});
}
return list;
}
function renderAttachment(att) {
return `
<fieldset style="border:1px solid #ddd; padding:10px; margin-top:20px; background:#f9f9f9;">
<legend style="font-weight:bold;">附件</legend>
📄 ${att.name} (${att.size}) <a href="#">[点击下载]</a>
</fieldset>
`;
}
function getCategoryName(cat) {
const map = { all: '全部主题', hardware: '硬件专区', software: '软件分享', water: '灌水吐槽', market: '二手交易', feedback: '站务公告' };
return map[cat] || '未知板块';
}
// --- Actions ---
function switchView(viewName) {
STATE.currentView = viewName;
// Reset layout if needed
document.getElementById('mainLayout').className = viewName === 'thread' ? 'container layout-grid thread-view' : 'container layout-grid';
renderApp();
}
function openThread(id) {
STATE.viewingThreadId = id;
switchView('thread');
}
function filterCategory(cat) {
STATE.currentCategory = cat;
switchView('home');
}
// Modal & Toast
function openModal(id) {
document.getElementById(id).classList.add('show');
}
function closeModal(id) {
document.getElementById(id).classList.remove('show');
}
function showToast(msg, type) {
const t = document.getElementById('toast');
t.innerText = msg;
t.style.display = 'block';
t.style.background = type === 'warning' ? '#ff9800' : (type === 'success' ? '#4caf50' : '#333');
setTimeout(() => t.style.display = 'none', 3000);
}
// Auth Simulation
function doLogin() {
const user = document.getElementById('loginUser').value;
closeModal('loginModal');
STATE.currentUser = { name: user || "User" };
showToast(`欢迎回来,${STATE.currentUser.name}`, 'success');
updateUserUI();
}
function updateUserUI() {
const nav = document.getElementById('navUser');
if (STATE.currentUser) {
nav.innerHTML = `
<div style="display:flex; align-items:center; gap:10px; cursor:pointer;">
<span style="font-weight:bold;">${STATE.currentUser.name}</span>
<div class="user-avatar-sm" style="background:#4caf50;"></div>
<button class="btn" style="padding:2px 8px; font-size:0.8rem;" onclick="location.reload()">注销</button>
</div>
`;
}
}
function formatDate(iso) {
return iso.replace('T', ' ').substring(0, 16);
}
function timeAgo(props) {
return "1小时前"; // Simplified
}
function insertText(prefix, suffix) {
const area = document.getElementById('newPostContent');
area.value += prefix + suffix;
}
function submitNewThread() {
closeModal('newThreadModal');
showToast('发布成功!(模拟)', 'success');
// Fake add
setTimeout(() => {
DB.threads.unshift({
id: 9999,
title: document.getElementById('newPostTitle').value || "无标题",
author: STATE.currentUser || DB.users[2],
replies: 0, views: 1, category: 'hardware',
date: new Date().toISOString(),
isHot: false
});
renderHome(document.getElementById('contentArea'));
}, 500);
}
// --- Init ---
window.onload = function() {
initData();
renderApp();
// Background Ping Simulation
setInterval(() => {
const ms = Math.floor(Math.random() * 50) + 10;
document.getElementById('pingValue').innerText = ms + 'ms';
document.getElementById('pingValue').style.color = ms > 100 ? 'red' : 'green';
}, 2000);
};
</script> </script>
</body> </body>

File diff suppressed because it is too large Load Diff

View File

@@ -4,6 +4,7 @@
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>BitMatrix Pro Exchange - BTC/USDT</title> <title>BitMatrix Pro Exchange - BTC/USDT</title>
<style> <style>
/* === 全局样式 === */ /* === 全局样式 === */
:root { :root {
@@ -35,6 +36,97 @@
h1, h2, h3, h4 { margin: 0; font-weight: 500; } h1, h2, h3, h4 { margin: 0; font-weight: 500; }
hr { border: 0; border-top: 1px solid var(--border); margin: 0; } 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 { #top-banner {
background: #2b3139; background: #2b3139;
@@ -217,7 +309,8 @@
#footer p { margin: 0; } #footer p { margin: 0; }
</style> </style>
</head> </head>
<body>
<body style="overflow-y: auto;">
<div id="app-root"> <div id="app-root">
@@ -252,13 +345,13 @@
<button type="button" style="display:none;"></button> <button type="button" style="display:none;"></button>
</form> </form>
<ul> <ul>
<li><a href="#">BTC/USDT - 98,542.00</a></li> <li onclick="switchMarket('BTC/USDT', 98542.00)"><a href="javascript:void(0)">BTC/USDT - 98,542.00</a></li>
<li><a href="#">ETH/USDT - 3,850.00</a></li> <li onclick="switchMarket('ETH/USDT', 3850.00)"><a href="javascript:void(0)">ETH/USDT - 3,850.00</a></li>
<li><a href="#">SOL/USDT - 145.20</a></li> <li onclick="switchMarket('SOL/USDT', 145.20)"><a href="javascript:void(0)">SOL/USDT - 145.20</a></li>
<li><a href="#">DOGE/USDT - 0.12</a></li> <li onclick="switchMarket('DOGE/USDT', 0.1205)"><a href="javascript:void(0)">DOGE/USDT - 0.1205</a></li>
<li><a href="#" style="color:#f6465d;">PEPE/USDT (热) - 0.00001</a></li> <li onclick="switchMarket('PEPE/USDT', 0.00001)"><a href="javascript:void(0)" style="color:#f6465d;">PEPE/USDT (热) - 0.00001</a></li>
<li><a href="#" style="color:#f6465d;">SCAM/USDT (新) - 1.00</a></li> <li onclick="switchMarket('SCAM/USDT', 1.00)"><a href="javascript:void(0)" style="color:#f6465d;">SCAM/USDT (新) - 1.00</a></li>
<li><a href="#">BNB/USDT - 600.00</a></li> <li onclick="switchMarket('BNB/USDT', 600.00)"><a href="javascript:void(0)">BNB/USDT - 600.00</a></li>
</ul> </ul>
<div style="margin-top:20px; color:#555; font-size:11px;"> <div style="margin-top:20px; color:#555; font-size:11px;">
@@ -272,14 +365,22 @@
<div id="center-panel"> <div id="center-panel">
<div id="chart-area"> <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> <h3>[Interactive K-Line Chart Loading...]</h3>
<p>TradingView Module not loaded.</p> <p>TradingView Module not loaded.</p>
<p>Loading scripts...</p> <p>Loading scripts...</p>
<p>Connecting to WebSocket wss://api.bitmatrix.com...</p> <p>Connecting to WebSocket wss://api.bitmatrix.com...</p>
</div> </div>
<div style="background-color: yellow;"> <!-- Delay 警告 -->
<small>Warning: Connection latency > 500ms. Data may be delayed.</small> <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>
</div> </div>
@@ -289,12 +390,12 @@
<div class="book-column"> <div class="book-column">
<h4>卖盘 (Asks)</h4> <h4>卖盘 (Asks)</h4>
<ul> <ul>
<li><span>98,545.00</span> - <span>0.52 BTC</span></li> <li onclick="fillForm(98545.00, 0.52)"><span>98,545.00</span> - <span>0.52 BTC</span></li>
<li><span>98,544.50</span> - <span>0.11 BTC</span></li> <li onclick="fillForm(98544.50, 0.11)"><span>98,544.50</span> - <span>0.11 BTC</span></li>
<li><span>98,544.00</span> - <span>1.20 BTC</span></li> <li onclick="fillForm(98544.00, 1.20)"><span>98,544.00</span> - <span>1.20 BTC</span></li>
<li><span>98,543.50</span> - <span>0.05 BTC</span></li> <li onclick="fillForm(98543.50, 0.05)"><span>98,543.50</span> - <span>0.05 BTC</span></li>
<li><span>98,543.00</span> - <span>0.88 BTC</span></li> <li onclick="fillForm(98543.00, 0.88)"><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(98542.50, 2.00)"><span>98,542.50</span> - <span>2.00 BTC</span></li>
</ul> </ul>
</div> </div>
@@ -303,28 +404,29 @@
</div> </div>
<div class="current-price"> <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>
<div class="book-column"> <div class="book-column">
<h4>买盘 (Bids)</h4> <h4>买盘 (Bids)</h4>
<ul> <ul>
<li><span>98,541.50</span> - <span>0.33 BTC</span></li> <li onclick="fillForm(98541.50, 0.33)"><span>98,541.50</span> - <span>0.33 BTC</span></li>
<li><span>98,541.00</span> - <span>5.00 BTC</span></li> <li onclick="fillForm(98541.00, 5.00)"><span>98,541.00</span> - <span>5.00 BTC</span></li>
<li><span>98,540.50</span> - <span>0.20 BTC</span></li> <li onclick="fillForm(98540.50, 0.20)"><span>98,540.50</span> - <span>0.20 BTC</span></li>
<li><span>98,540.00</span> - <span>1.50 BTC</span></li> <li onclick="fillForm(98540.00, 1.50)"><span>98,540.00</span> - <span>1.50 BTC</span></li>
<li><span>98,539.50</span> - <span>0.10 BTC</span></li> <li onclick="fillForm(98539.50, 0.10)"><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(98539.00, 0.01)"><span>98,539.00</span> - <span>0.01 BTC</span></li>
</ul> </ul>
</div> </div>
</div> </div>
</div> </div>
<!-- 右侧:交易与聊天 -->
<div id="right-panel"> <div id="right-panel">
<div id="trade-form"> <div id="trade-form">
<h3>现货交易</h3> <h3>现货交易</h3>
<form> <form onsubmit="event.preventDefault();">
<div> <div>
<label>类型:</label> <label>类型:</label>
<input type="radio" name="type" checked> 限价 <input type="radio" name="type" checked> 限价
@@ -344,23 +446,37 @@
<br><small>借币利率 0.05%/天</small> <br><small>借币利率 0.05%/天</small>
</div> </div>
<p style="margin-bottom: 10px; color:#aaa;">可用余额: Loading...</p>
<div class="btn-group"> <div class="btn-group">
<button type="button" onclick="executeTrade('buy')">买入 BTC</button> <button type="button" onclick="executeTrade('buy')">买入 BTC</button>
<button type="button" onclick="executeTrade('sell')">卖出 BTC</button> <button type="button" onclick="executeTrade('sell')">卖出 BTC</button>
</div> </div>
</form> </form>
<p style="margin-top:10px; color:#aaa;">可用余额: 0.00 USDT <a href="#" style="color:#fcd535;">[充值]</a></p>
</div> </div>
<div id="recent-trades"> <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;">
<ul id="trade-list"> <button class="trade-tab active" id="tab-btn-recent" onclick="switchTradeTab('recent')">最新成交</button>
<li><small>12:00:01</small> - 98,542.00 - 0.0021</li> <button class="trade-tab" id="tab-btn-orders" onclick="switchTradeTab('orders')">当前委托</button>
<li><small>12:00:02</small> - 98,541.50 - 0.0100</li> </div>
<li><small>12:00:02</small> - 98,542.10 - 0.5000</li>
<li><small>12:00:03</small> - 98,542.00 - 0.0001</li> <div id="trade-list-container">
<li><small>12:00:05</small> - 98,542.00 - 0.0332</li> <ul id="trade-list">
</ul> <li><small>12:00:01</small> - 98,542.00 - 0.0021</li>
<li><small>12:00:02</small> - 98,541.50 - 0.0100</li>
<li><small>12:00:02</small> - 98,542.10 - 0.5000</li>
<li><small>12:00:03</small> - 98,542.00 - 0.0001</li>
<li><small>12:00:05</small> - 98,542.00 - 0.0332</li>
</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>
<div id="chat-room"> <div id="chat-room">
@@ -384,6 +500,197 @@
</div> </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"> <div id="footer">
<p>联系我们 | API 文档 | 费率标准 | 上币申请</p> <p>联系我们 | API 文档 | 费率标准 | 上币申请</p>
<p>© 2025 BitMatrix. All rights reserved.</p> <p>© 2025 BitMatrix. All rights reserved.</p>
@@ -394,15 +701,313 @@
</div> </div>
<script> <script>
function executeTrade(type) { // System State
if(type === 'buy') { const SYSTEM_STATE = {
alert("错误:可用 USDT 余额不足,请充值。"); 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 { } 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(() => { setInterval(() => {
const priceEl = document.getElementById('header-price'); const priceEl = document.getElementById('header-price');
let current = parseFloat(priceEl.innerText.replace(',','')); let current = parseFloat(priceEl.innerText.replace(',',''));
@@ -410,15 +1015,37 @@
let newPrice = (current + change).toFixed(2); let newPrice = (current + change).toFixed(2);
priceEl.innerText = newPrice; priceEl.innerText = newPrice;
// 同时也往成交列表加一条假数据 // Also add fake trades occasionally
const list = document.getElementById('trade-list'); if(Math.random() > 0.3) {
const li = document.createElement('li'); const list = document.getElementById('trade-list');
li.innerHTML = `<small>12:00:0${Math.floor(Math.random()*9)}</small> - ${newPrice} - ${(Math.random()).toFixed(4)}`; const li = document.createElement('li');
li.style.color = change > 0 ? '#0ecb81' : '#f6465d'; const now = new Date();
list.prepend(li); const timeStr = now.toTimeString().split(' ')[0];
if(list.children.length > 20) list.lastElementChild.remove(); 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); }, 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> </script>
</body> </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

11526
zhihu/001.html Normal file

File diff suppressed because one or more lines are too long

12833
zhihu/002.html Normal file

File diff suppressed because one or more lines are too long

14880
zhihu/003.html Normal file

File diff suppressed because one or more lines are too long

17565
zhihu/004.html Normal file

File diff suppressed because one or more lines are too long

24275
zhihu/005.html Normal file

File diff suppressed because one or more lines are too long

25726
zhihu/006.html Normal file

File diff suppressed because one or more lines are too long

26708
zhihu/007.html Normal file

File diff suppressed because one or more lines are too long

30
zhihu/record.json Normal file
View File

@@ -0,0 +1,30 @@
{
"step-1": {
"query": "我想要回答一个问题,请你先帮我看看有哪些消息",
"grounding_area": ""
},
"step-2": {
"query": "请你帮我找到2026年1月份最早请我回答的问题并跳转到该问题详情页",
"grounding_area": ""
},
"step-3": {
"query": "请你帮我给最长的回答一个赞同",
"grounding_area": ""
},
"step-4": {
"query": "我想要回答,请你进入回答问题界面",
"grounding_area": ""
},
"step-5": {
"query": "现在可能默认开启了markdown语法请你先找到该设置在哪里",
"grounding_area": ""
},
"step-6": {
"query": "请你关闭markdown语法",
"grounding_area": ""
},
"step-7": {
"query": "帮我用纯文本格式填写一个回答该问题的内容",
"grounding_area": ""
}
}