basic test
This commit is contained in:
817
003/3-all.html
Normal file
817
003/3-all.html
Normal file
@@ -0,0 +1,817 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Cloud Resource Manager - Zone CN-East-2</title>
|
||||
<style>
|
||||
/* Global Settings */
|
||||
:root {
|
||||
--primary: #108ee9;
|
||||
--success: #00a854;
|
||||
--warning: #ffbf00;
|
||||
--danger: #f04134;
|
||||
--bg-body: #f5f5f5;
|
||||
--bg-panel: #ffffff;
|
||||
--border: #e9e9e9;
|
||||
--text-main: #333;
|
||||
--text-sub: #999;
|
||||
}
|
||||
|
||||
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; background: var(--bg-body); color: var(--text-main); margin: 0; font-size: 12px; }
|
||||
h2, h3 { margin: 0; font-weight: 500; }
|
||||
ul { padding: 0; list-style: none; }
|
||||
a { text-decoration: none; color: var(--primary); transition: 0.3s; }
|
||||
a:hover { color: #40a9ff; }
|
||||
hr { border: 0; border-top: 1px solid var(--border); margin: 10px 0; }
|
||||
|
||||
/* Top Navigation */
|
||||
.header { background: #262f3e; color: #fff; padding: 0 20px; height: 50px; display: flex; align-items: center; justify-content: space-between; }
|
||||
.header h2 { font-size: 16px; color: #fff; }
|
||||
.header p { color: #aaa; margin-left: 20px; }
|
||||
.header nav a { color: #ddd; margin: 0 10px; font-size: 13px; }
|
||||
.header nav a:hover { color: #fff; }
|
||||
|
||||
/* Main Layout */
|
||||
.layout-container { display: flex; min-height: calc(100vh - 50px); }
|
||||
|
||||
/* Sidebar */
|
||||
.sidebar { width: 220px; background: #fff; border-right: 1px solid var(--border); padding: 20px; flex-shrink: 0; }
|
||||
.sidebar h3 { font-size: 13px; color: var(--text-main); margin-bottom: 10px; margin-top: 20px; font-weight: bold; }
|
||||
.sidebar li { margin-bottom: 8px; }
|
||||
.sidebar li a { color: #666; display: block; padding: 5px; border-radius: 4px; }
|
||||
.sidebar li a:hover { background: #e6f7ff; color: var(--primary); }
|
||||
|
||||
.quota-box { background: #fafafa; padding: 10px; border-radius: 4px; border: 1px solid #eee; }
|
||||
.quota-box p { margin: 5px 0; color: #666; }
|
||||
|
||||
/* Ad Interference - Sidebar */
|
||||
.ad-sidebar { margin-top: 20px; padding: 10px; background: linear-gradient(135deg, #f0f5ff 0%, #d6e4ff 100%); border-radius: 4px; border: 1px solid #adc6ff; }
|
||||
.ad-sidebar p { margin: 0; color: #1d39c4; }
|
||||
|
||||
/* Main Content Area */
|
||||
.main-content { flex: 1; padding: 20px; overflow-x: auto; }
|
||||
|
||||
/* Top Notification - Interference */
|
||||
.system-notice { background: #fffbe6; border: 1px solid #ffe58f; padding: 10px 15px; border-radius: 4px; display: flex; flex-direction: column; margin-bottom: 20px; }
|
||||
.system-notice strong { color: #fa8c16; margin-bottom: 5px; }
|
||||
.system-notice p { margin: 0; color: #666; }
|
||||
|
||||
/* Search Bar */
|
||||
.search-bar fieldset { border: 0; padding: 0; margin: 0; background: #fff; padding: 15px; border-radius: 4px; display: flex; align-items: center; gap: 10px; box-shadow: 0 1px 2px rgba(0,0,0,0.05); }
|
||||
.search-bar legend { display: none; }
|
||||
.search-bar label { font-weight: 500; }
|
||||
.search-bar input, .search-bar select { border: 1px solid #d9d9d9; padding: 5px 8px; border-radius: 4px; outline: none; }
|
||||
.search-bar button { background: #fff; border: 1px solid #d9d9d9; padding: 5px 15px; border-radius: 4px; cursor: pointer; }
|
||||
.search-bar button:hover { color: var(--primary); border-color: var(--primary); }
|
||||
|
||||
/* Action Buttons Area */
|
||||
.toolbar { margin: 15px 0; }
|
||||
.toolbar button { margin-right: 8px; padding: 6px 15px; background: #fff; border: 1px solid #d9d9d9; border-radius: 4px; cursor: pointer; }
|
||||
.toolbar button:first-child { background: var(--primary); color: #fff; border-color: var(--primary); }
|
||||
|
||||
/* Instance List Table */
|
||||
.instance-list { background: #fff; border-radius: 4px; box-shadow: 0 1px 2px rgba(0,0,0,0.05); }
|
||||
|
||||
/* List Header */
|
||||
.list-header { display: grid; grid-template-columns: 40px 3fr 2fr 2fr 1.5fr 3fr; padding: 12px 15px; background: #fafafa; border-bottom: 1px solid #e9e9e9; font-weight: 600; color: #666; }
|
||||
|
||||
/* List Row */
|
||||
.list-row { display: grid; grid-template-columns: 40px 3fr 2fr 2fr 1.5fr 3fr; padding: 15px; border-bottom: 1px solid #e9e9e9; align-items: center; transition: background 0.2s; }
|
||||
.list-row:hover { background: #f0f7ff; }
|
||||
|
||||
/* Inline Styles */
|
||||
.list-row strong { color: var(--primary); cursor: pointer; display: block; margin-bottom: 4px; }
|
||||
.list-row small { color: #999; }
|
||||
|
||||
/* Status Colors */
|
||||
.status-running { color: var(--success); display: inline-flex; align-items: center; }
|
||||
.status-running::before { content: ''; width: 6px; height: 6px; background: var(--success); border-radius: 50%; margin-right: 5px; }
|
||||
|
||||
.status-stopped { color: #999; display: inline-flex; align-items: center; }
|
||||
.status-stopped::before { content: ''; width: 6px; height: 6px; background: #ccc; border-radius: 50%; margin-right: 5px; }
|
||||
|
||||
.status-maintenance { color: var(--warning); }
|
||||
|
||||
/* Button Group - Hide dangerous buttons, simulate dropdown */
|
||||
.action-group { display: flex; gap: 8px; flex-wrap: wrap; }
|
||||
.action-group button { border: none; background: none; color: var(--primary); cursor: pointer; padding: 0; }
|
||||
.action-group button:hover { text-decoration: underline; }
|
||||
/* Dangerous operations hidden by default */
|
||||
.btn-danger { color: var(--danger) !important; display: none; /* Hide via CSS */ }
|
||||
.list-row:hover .btn-danger { display: inline-block; /* Show on hover */ }
|
||||
|
||||
/* Ad Interferences */
|
||||
.ad-row { background: #f9f9f9; border: 1px dashed #d9d9d9; margin: 10px; border-radius: 4px; }
|
||||
.ad-row strong { color: #333 !important; }
|
||||
.error-row { display: none; } /* Hide error info */
|
||||
.billing-alert-row { background: #fff1f0; border: 1px solid #ffa39e; margin: 10px; border-radius: 4px; }
|
||||
.billing-alert-row p { margin: 0; display: inline-block; color: #f5222d; margin-right: 10px; }
|
||||
|
||||
/* Footer */
|
||||
.footer { padding: 20px; text-align: center; color: #ccc; font-size: 12px; }
|
||||
|
||||
/* Pagination */
|
||||
.pagination { display: flex; align-items: center; justify-content: flex-end; padding: 15px; gap: 10px; }
|
||||
.pagination button { background: #fff; border: 1px solid #d9d9d9; padding: 5px 10px; border-radius: 4px; cursor: pointer; }
|
||||
|
||||
/* === New Interactive Elements === */
|
||||
/* Modal */
|
||||
.modal-overlay { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.5); display: none; justify-content: center; align-items: center; z-index: 1000; }
|
||||
.modal-content { background: #fff; width: 500px; padding: 20px; border-radius: 4px; box-shadow: 0 4px 12px rgba(0,0,0,0.15); animation: fadeIn 0.3s; }
|
||||
.modal-header { font-size: 16px; font-weight: bold; margin-bottom: 15px; border-bottom: 1px solid #eee; padding-bottom: 10px; display: flex; justify-content: space-between; }
|
||||
|
||||
/* Drawer (Right Panel) */
|
||||
.drawer-overlay { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.2); z-index: 900; display: none; }
|
||||
.drawer { position: fixed; top: 0; right: -450px; width: 450px; height: 100%; background: #fff; box-shadow: -2px 0 8px rgba(0,0,0,0.1); transition: right 0.3s ease; z-index: 901; display: flex; flex-direction: column; }
|
||||
.drawer.open { right: 0; }
|
||||
.drawer-header { padding: 20px; border-bottom: 1px solid #eee; background: #fafafa; display: flex; justify-content: space-between; align-items: center; }
|
||||
.drawer-body { padding: 20px; flex: 1; overflow-y: auto; }
|
||||
|
||||
/* Toast Notification */
|
||||
.toast { position: fixed; top: 20px; left: 50%; transform: translateX(-50%); background: #333; color: #fff; padding: 10px 20px; border-radius: 4px; z-index: 2000; display: none; opacity: 0; transition: opacity 0.3s; }
|
||||
.toast.show { display: block; opacity: 1; }
|
||||
|
||||
/* Form Styles */
|
||||
.form-group { margin-bottom: 15px; }
|
||||
.form-group label { display: block; margin-bottom: 5px; color: #666; font-weight: 500; }
|
||||
.form-input { width: 100%; padding: 8px; border: 1px solid #d9d9d9; border-radius: 4px; box-sizing: border-box; }
|
||||
|
||||
@keyframes fadeIn { from { opacity: 0; transform: translateY(-10px); } to { opacity: 1; transform: translateY(0); } }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="main-wrapper">
|
||||
<div class="header">
|
||||
<h2>HyperCloud Console [Enterprise]</h2>
|
||||
<p>Current Region: <strong>CN-East-2</strong> | Account: admin_core_team</p>
|
||||
<nav>
|
||||
<a href="#">Overview</a> |
|
||||
<a href="#">Instances (ECI)</a> |
|
||||
<a href="#">Object Storage (OSS)</a> |
|
||||
<a href="#">VPC</a> |
|
||||
<a href="#">Security Groups</a> |
|
||||
<a href="#">Load Balancer</a> |
|
||||
<a href="#">Billing</a> |
|
||||
<a href="#">Support</a>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
<div class="layout-container">
|
||||
<div class="sidebar">
|
||||
<h3>Resources</h3>
|
||||
<ul>
|
||||
<li><a href="javascript:void(0)" class="active" onclick="filterByStatus('all', this)">All Instances (14)</a></li>
|
||||
<li><a href="javascript:void(0)" onclick="filterByStatus('running', this)">Running (10)</a></li>
|
||||
<li><a href="javascript:void(0)" onclick="filterByStatus('stopped', this)">Stopped (3)</a></li>
|
||||
<li><a href="javascript:void(0)" onclick="filterByStatus('maintenance', this)">Abnormal/Maintenance (1)</a></li>
|
||||
</ul>
|
||||
|
||||
<h3>Quota Monitor</h3>
|
||||
<div class="quota-box">
|
||||
<p>vCPU Usage: 88/100 Cores</p>
|
||||
<p>RAM Usage: 256/512 GB</p>
|
||||
<p>Public IP: 12/20</p>
|
||||
</div>
|
||||
|
||||
<div class="ad-sidebar">
|
||||
<p><strong>[Promo] GPU Instance 20% Off</strong><br>A100 available now...</p>
|
||||
</div>
|
||||
|
||||
<h3>Operation Logs</h3>
|
||||
<ul style="font-size: 11px; color: #999;">
|
||||
<li><small>2025-12-21 10:00: inst-a1 Rebooted</small></li>
|
||||
<li><small>2025-12-21 09:45: Security Group Updated</small></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="main-content">
|
||||
<div class="system-notice">
|
||||
<strong>[Urgent] Zone B Network Maintenance (CN-East-2)</strong>
|
||||
<p>Fiber optic cutover scheduled for this Sunday at 02:00 AM. Expect 2 network jitters of 5 seconds each.</p>
|
||||
</div>
|
||||
|
||||
<form class="search-bar">
|
||||
<fieldset>
|
||||
<label>Keyword:</label> <input type="text" id="searchInput" placeholder="Instance ID / Name">
|
||||
<label>Tag:</label> <input type="text" placeholder="Key:Value">
|
||||
<label>Billing Type:</label>
|
||||
<select>
|
||||
<option>All</option>
|
||||
<option>Subscription</option>
|
||||
<option>Pay-As-You-Go</option>
|
||||
<option>Preemptible</option>
|
||||
</select>
|
||||
<button type="button" class="btn-primary" onclick="searchInstances()">Refresh</button>
|
||||
<button type="button" onclick="resetSearch()">Reset</button>
|
||||
</fieldset>
|
||||
</form>
|
||||
|
||||
<div class="toolbar">
|
||||
<button style="background: var(--primary); color: #fff; border-color: var(--primary);" onclick="openCreateModal()">+ Create Instance</button>
|
||||
<button onclick="performToolbarAction('start')">Start</button>
|
||||
<button onclick="performToolbarAction('stop')">Stop</button>
|
||||
<button onclick="performToolbarAction('restart')">Restart</button>
|
||||
<button onclick="showToast('Feature in development: Release Settings', 'warning')">Release Settings</button>
|
||||
<button onclick="showToast('Feature in development: Change Billing', 'warning')">Change Billing</button>
|
||||
</div>
|
||||
|
||||
<div class="instance-list">
|
||||
<div class="list-header">
|
||||
<span><input type="checkbox" id="selectAll"></span>
|
||||
<span><strong>Instance ID/Name</strong></span>
|
||||
<span><strong>IP Address (Public/Private)</strong></span>
|
||||
<span><strong>Spec</strong></span>
|
||||
<span><strong>Status</strong></span>
|
||||
<span><strong>Actions</strong></span>
|
||||
</div>
|
||||
|
||||
<div class="list-row">
|
||||
<div>
|
||||
<input type="checkbox" class="row-checkbox">
|
||||
</div>
|
||||
<div>
|
||||
<strong onclick="alert('Go to Detail Page')">i-bp1j2k3l4m5n (Web-Server-01)</strong><br>
|
||||
<small>Image: Ubuntu 22.04 LTS</small>
|
||||
</div>
|
||||
<div>
|
||||
<span>139.196.xxx.xxx</span><br>
|
||||
<span style="color:#999">192.168.1.101</span>
|
||||
</div>
|
||||
<div>
|
||||
<span>4 vCPU</span><br>
|
||||
<span>16 GiB</span>
|
||||
</div>
|
||||
<div>
|
||||
<span class="status-running">Running</span>
|
||||
</div>
|
||||
<div class="action-group">
|
||||
<button onclick="remoteConnect('i-bp1j2k3l4m5n')">Connect</button>
|
||||
<button onclick="openMonitor('i-bp1j2k3l4m5n')">Monitor</button>
|
||||
<button onclick="showMoreMenu(this)">More...</button>
|
||||
<button class="btn-danger" onclick="confirmDelete('i-bp1j2k3l4m5n')">Force Stop</button>
|
||||
<button class="btn-danger" onclick="confirmDelete('i-bp1j2k3l4m5n', true)">Terminate</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="list-row">
|
||||
<div>
|
||||
<input type="checkbox" class="row-checkbox">
|
||||
</div>
|
||||
<div>
|
||||
<strong onclick="alert('Go to Detail Page')">i-bp1x9y8z7a6b (DB-Master-Prod)</strong><br>
|
||||
<small>Image: CentOS 7.9 (EOL)</small>
|
||||
</div>
|
||||
<div>
|
||||
<span>47.100.xxx.xxx</span><br>
|
||||
<span style="color:#999">192.168.1.200</span>
|
||||
</div>
|
||||
<div>
|
||||
<span>16 vCPU</span><br>
|
||||
<span>64 GiB</span>
|
||||
</div>
|
||||
<div>
|
||||
<span class="status-running">Running</span> <small>(High Load)</small>
|
||||
</div>
|
||||
<div class="action-group">
|
||||
<button>Connect</button>
|
||||
<button>Monitor</button>
|
||||
<button>More...</button>
|
||||
<button class="btn-danger" onclick="confirmDelete()">Force Stop</button>
|
||||
<button class="btn-danger" onclick="confirmDelete()">Terminate</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="list-row ad-row">
|
||||
<div>
|
||||
<input type="checkbox" disabled>
|
||||
</div>
|
||||
<div>
|
||||
<strong>[Recommended] AutoScaling Service</strong><br>
|
||||
<small>Automatically manage your instance count</small>
|
||||
</div>
|
||||
<div>
|
||||
<span>--</span>
|
||||
</div>
|
||||
<div>
|
||||
<span>Dynamic</span>
|
||||
</div>
|
||||
<div>
|
||||
<span>Not Enabled</span>
|
||||
</div>
|
||||
<div class="action-group">
|
||||
<button style="color: #fa8c16; font-weight:bold;" onclick="openProductIntro('scaling')">Enable</button>
|
||||
<button onclick="openProductIntro('scaling_doc')">Learn More</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="list-row">
|
||||
<div>
|
||||
<input type="checkbox" class="row-checkbox">
|
||||
</div>
|
||||
<div>
|
||||
<strong onclick="alert('Go to Detail Page')">i-bp1h5g6f4d3s (Redis-Cache-01)</strong><br>
|
||||
<small>Image: Redis Enterprise</small>
|
||||
</div>
|
||||
<div>
|
||||
<span style="color:#ccc">(No Public IP)</span><br>
|
||||
<span style="color:#999">192.168.1.105</span>
|
||||
</div>
|
||||
<div>
|
||||
<span>2 vCPU</span><br>
|
||||
<span>8 GiB</span>
|
||||
</div>
|
||||
<div>
|
||||
<span class="status-stopped">Stopped</span>
|
||||
</div>
|
||||
<div class="action-group">
|
||||
<button>Connect</button>
|
||||
<button>Monitor</button>
|
||||
<button>More...</button>
|
||||
<button class="btn-danger" onclick="confirmDelete()">Force Stop</button>
|
||||
<button class="btn-danger" onclick="confirmDelete()">Terminate</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="list-row error-row">
|
||||
<div align="center" style="width: 100%;">
|
||||
<small>Error: Failed to fetch metric data for instance i-bp1h5... (Retrying in 5s)</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="list-row">
|
||||
<div>
|
||||
<input type="checkbox" class="row-checkbox">
|
||||
</div>
|
||||
<div>
|
||||
<strong onclick="alert('Go to Detail Page')">i-bp1q2w3e4r5t (Worker-Node-A)</strong><br>
|
||||
<small>Image: Aliyun Linux 3</small>
|
||||
</div>
|
||||
<div>
|
||||
<span>101.200.xxx.xxx</span><br>
|
||||
<span style="color:#999">172.16.0.12</span>
|
||||
</div>
|
||||
<div>
|
||||
<span>8 vCPU</span><br>
|
||||
<span>32 GiB</span>
|
||||
</div>
|
||||
<div>
|
||||
<span class="status-running">Running</span>
|
||||
</div>
|
||||
<div class="action-group">
|
||||
<button>Connect</button>
|
||||
<button>Monitor</button>
|
||||
<button>More...</button>
|
||||
<button class="btn-danger" onclick="confirmDelete()">Force Stop</button>
|
||||
<button class="btn-danger" onclick="confirmDelete()">Terminate</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="list-row">
|
||||
<div>
|
||||
<input type="checkbox" class="row-checkbox">
|
||||
</div>
|
||||
<div>
|
||||
<strong onclick="alert('Go to Detail Page')">i-bp1a2s3d4f5g (Worker-Node-B)</strong><br>
|
||||
<small>Image: Aliyun Linux 3</small>
|
||||
</div>
|
||||
<div>
|
||||
<span>101.200.xxx.xxx</span><br>
|
||||
<span style="color:#999">172.16.0.13</span>
|
||||
</div>
|
||||
<div>
|
||||
<span>8 vCPU</span><br>
|
||||
<span>32 GiB</span>
|
||||
</div>
|
||||
<div>
|
||||
<span class="status-running">Starting...</span>
|
||||
</div>
|
||||
<div class="action-group">
|
||||
<button>Connect</button>
|
||||
<button>Monitor</button>
|
||||
<button>More...</button>
|
||||
<button class="btn-danger" onclick="confirmDelete()">Force Stop</button>
|
||||
<button class="btn-danger" onclick="confirmDelete()">Terminate</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="list-row">
|
||||
<div>
|
||||
<input type="checkbox" class="row-checkbox">
|
||||
</div>
|
||||
<div>
|
||||
<strong onclick="alert('Go to Detail Page')">i-bp1z2x3c4v5b (Legacy-System-Win)</strong><br>
|
||||
<small>Image: Windows Server 2012 R2</small>
|
||||
</div>
|
||||
<div>
|
||||
<span>121.40.xxx.xxx</span><br>
|
||||
<span style="color:#999">192.168.1.99</span>
|
||||
</div>
|
||||
<div>
|
||||
<span>4 vCPU</span><br>
|
||||
<span>8 GiB</span>
|
||||
</div>
|
||||
<div>
|
||||
<span class="status-maintenance">Maintenance</span>
|
||||
</div>
|
||||
<div class="action-group">
|
||||
<button>Connect</button>
|
||||
<button>Monitor</button>
|
||||
<button>More...</button>
|
||||
<button class="btn-danger" onclick="confirmDelete()">Force Stop</button>
|
||||
<button class="btn-danger" onclick="confirmDelete()">Terminate</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="list-row billing-alert-row">
|
||||
<div style="grid-column: 1 / -1;">
|
||||
<strong>[Billing Alert] Insufficient Balance (< 100.00 CNY)</strong>
|
||||
</div>
|
||||
<div style="grid-column: 1 / -1; margin-top: 5px;">
|
||||
<p>Please top up immediately to avoid service interruption.</p>
|
||||
<button onclick="openRecharge()" style="background: #f5222d; color: white; border: none; padding: 4px 12px; border-radius: 2px;">Top Up</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="list-row">
|
||||
<div>
|
||||
<input type="checkbox" class="row-checkbox">
|
||||
</div>
|
||||
<div>
|
||||
<strong onclick="alert('Go to Detail Page')">i-bp1m0n9b8v7c (Dev-Test-Env)</strong><br>
|
||||
<small>Image: Ubuntu 20.04</small>
|
||||
</div>
|
||||
<div>
|
||||
<span style="color:#ccc">(No Public IP)</span><br>
|
||||
<span style="color:#999">192.168.50.50</span>
|
||||
</div>
|
||||
<div>
|
||||
<span>1 vCPU</span><br>
|
||||
<span>1 GiB</span>
|
||||
</div>
|
||||
<div>
|
||||
<span class="status-stopped">Stopped</span> <small>(Locked)</small>
|
||||
</div>
|
||||
<div class="action-group">
|
||||
<button>Connect</button>
|
||||
<button>Monitor</button>
|
||||
<button>More...</button>
|
||||
<button class="btn-danger" onclick="confirmDelete()">Force Stop</button>
|
||||
<button class="btn-danger" onclick="confirmDelete()">Terminate</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="pagination">
|
||||
<button onclick="changePage(-1)">< Previous</button>
|
||||
<span id="pageInfo">Page 1 / 5</span>
|
||||
<button onclick="changePage(1)">Next ></button>
|
||||
<select onchange="changePageSize(this)">
|
||||
<option>10 / page</option>
|
||||
<option>20 / page</option>
|
||||
<option>50 / page</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="footer">
|
||||
<p>© 2025 HyperCloud Inc. | <a href="#">Privacy Policy</a> | <a href="#">Terms of Service</a></p>
|
||||
<p>Page generated in: 182ms | Request ID: req_uuid_998877</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Components -->
|
||||
|
||||
<!-- Create Instance Modal -->
|
||||
<div id="createModal" class="modal-overlay">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<span>Create New Instance (ECI)</span>
|
||||
<span onclick="closeCreateModal()" style="cursor:pointer; color:#999;">✕</span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Instance Name</label>
|
||||
<input type="text" id="newInstanceName" class="form-input" placeholder="E.g., Web-Server-02">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Image</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>Spec</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;">Cancel</button>
|
||||
<button onclick="confirmCreate()" style="padding: 6px 15px; background: var(--primary); color: #fff; border: none; cursor: pointer; border-radius: 4px;">Buy Now</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>Monitoring Overview (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;">Configuration</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('Order submitted, initializing instance...');
|
||||
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>Image: 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">Starting...</span></div>
|
||||
<div class="action-group">
|
||||
<button>Manage</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
|
||||
// Select All
|
||||
document.getElementById('selectAll').addEventListener('change', function(e) {
|
||||
const checkboxes = document.querySelectorAll('.row-checkbox');
|
||||
checkboxes.forEach(box => {
|
||||
box.checked = e.target.checked;
|
||||
});
|
||||
});
|
||||
|
||||
function performAction(action) {
|
||||
// Get selected
|
||||
const checkboxes = document.querySelectorAll('.row-checkbox:checked');
|
||||
if (checkboxes.length === 0) {
|
||||
alert('Please select at least one instance first');
|
||||
return;
|
||||
}
|
||||
|
||||
const count = checkboxes.length;
|
||||
if(confirm(`Are you sure you want to perform [${action.toUpperCase()}] on ${count} selected instances?`)) {
|
||||
showToast(`Command sent: ${action.toUpperCase()} ${count} instances`);
|
||||
// Reset selection
|
||||
checkboxes.forEach(c => c.checked = false);
|
||||
document.getElementById('selectAll').checked = false;
|
||||
}
|
||||
}
|
||||
|
||||
// High Risk Double Confirm
|
||||
function confirmDelete() {
|
||||
const userInput = prompt("High Risk Action!\nPlease type 'DELETE' to confirm termination:");
|
||||
if (userInput === 'DELETE') {
|
||||
showToast('Operation submitted: Instance is terminating...');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// 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('Running') || statusText.includes('Starting'))) show = true;
|
||||
else if (status === 'stopped' && statusText.includes('Stopped')) show = true;
|
||||
else if (status === 'maintenance' && statusText.includes('Maintenance')) show = true;
|
||||
|
||||
row.style.display = show ? 'grid' : 'none';
|
||||
});
|
||||
showToast(`Filtered by: ${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('Please select instances to operate on');
|
||||
return;
|
||||
}
|
||||
showToast(`Executing [${action}] on ${checkboxes.length} instances...`);
|
||||
setTimeout(() => {
|
||||
showToast('Operation command sent');
|
||||
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 + ' - Live Monitor');
|
||||
}
|
||||
|
||||
function showMoreMenu(btn) {
|
||||
// Simple fallback
|
||||
const actions = ['Create Snapshot', 'Change Spec', 'Reset Password', 'Replace OS'];
|
||||
const action = prompt(`[${actions.join(' | ')}]\nEnter operation to execute:`, actions[0]);
|
||||
if(action) {
|
||||
showToast(`Executing: ${action}`);
|
||||
}
|
||||
}
|
||||
|
||||
// 4. Search Bar
|
||||
function searchInstances() {
|
||||
const val = document.getElementById('searchInput').value;
|
||||
if(!val) {
|
||||
// refresh
|
||||
showToast('List refreshed successfully');
|
||||
// reset filters
|
||||
filterByStatus('all', document.querySelector('.sidebar a.active'));
|
||||
} else {
|
||||
showToast(`Searching for "${val}"...`);
|
||||
}
|
||||
}
|
||||
|
||||
function resetSearch() {
|
||||
document.getElementById('searchInput').value = '';
|
||||
// Trigger input event to clear filter
|
||||
document.getElementById('searchInput').dispatchEvent(new Event('input'));
|
||||
showToast('Search criteria reset');
|
||||
}
|
||||
|
||||
// 5. Pagination
|
||||
let currentPage = 1;
|
||||
function changePage(dir) {
|
||||
const newPage = currentPage + dir;
|
||||
if(newPage < 1 || newPage > 5) return;
|
||||
|
||||
currentPage = newPage;
|
||||
document.getElementById('pageInfo').innerText = `Page ${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(`Page size updated: ${select.value}`);
|
||||
}
|
||||
|
||||
// 6. Billing & Ads
|
||||
function openRecharge() {
|
||||
if(confirm("Redirect to payment gateway (Alipay/WeChat)?")) {
|
||||
showToast("Redirecting to payment page...");
|
||||
}
|
||||
}
|
||||
|
||||
function openProductIntro(product) {
|
||||
showToast(`Opening product docs: ${product}...`);
|
||||
}
|
||||
|
||||
// Override generic confirmDelete
|
||||
window.confirmDelete = function(instanceId, isHard) {
|
||||
if(confirm(`Warning: Are you sure you want to ${isHard ? 'terminate' : 'force stop'} instance [${instanceId}]?\nThis action is irreversible!`)) {
|
||||
showToast('Operation submitted');
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user