2587 lines
98 KiB
HTML
2587 lines
98 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>NEON-OS | 赛博朋克未来操作系统</title>
|
||
|
||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||
<link href="https://fonts.googleapis.com/css2?family=Orbitron:wght@400;500;700;900&family=Roboto+Mono:wght@300;400;500&display=swap" rel="stylesheet">
|
||
|
||
<style>
|
||
:root {
|
||
--neon-pink: #ff2a6d;
|
||
--neon-blue: #05d9e8;
|
||
--neon-purple: #d100d1;
|
||
--neon-cyan: #00ff9f;
|
||
--dark-bg: #0d0d16;
|
||
--glass-bg: rgba(13, 13, 22, 0.7);
|
||
--glass-border: rgba(5, 217, 232, 0.3);
|
||
--scan-line: rgba(0, 255, 159, 0.05);
|
||
--grid-color: rgba(255, 42, 109, 0.1);
|
||
}
|
||
|
||
* {
|
||
margin: 0;
|
||
padding: 0;
|
||
box-sizing: border-box;
|
||
user-select: none;
|
||
}
|
||
|
||
body {
|
||
font-family: 'Roboto Mono', monospace;
|
||
background-color: var(--dark-bg);
|
||
color: var(--neon-blue);
|
||
overflow: hidden;
|
||
height: 100vh;
|
||
width: 100vw;
|
||
position: relative;
|
||
}
|
||
|
||
/* 桌面背景 */
|
||
.desktop-bg {
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
width: 100%;
|
||
height: 100%;
|
||
background:
|
||
linear-gradient(rgba(13, 13, 22, 0.9), rgba(13, 13, 22, 0.7)),
|
||
repeating-linear-gradient(0deg, transparent, transparent 2px, var(--grid-color) 2px, var(--grid-color) 3px),
|
||
repeating-linear-gradient(90deg, transparent, transparent 2px, var(--grid-color) 2px, var(--grid-color) 3px);
|
||
z-index: -2;
|
||
}
|
||
|
||
.scan-lines {
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
width: 100%;
|
||
height: 100%;
|
||
background: linear-gradient(to bottom, transparent 50%, var(--scan-line) 51%);
|
||
background-size: 100% 4px;
|
||
z-index: -1;
|
||
animation: scanline 8s linear infinite;
|
||
pointer-events: none;
|
||
}
|
||
|
||
@keyframes scanline {
|
||
0% { background-position: 0 0; }
|
||
100% { background-position: 0 100%; }
|
||
}
|
||
|
||
/* 开机动画 */
|
||
#boot-screen {
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
width: 100%;
|
||
height: 100%;
|
||
background: var(--dark-bg);
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: center;
|
||
align-items: center;
|
||
z-index: 10000;
|
||
transition: opacity 0.5s ease;
|
||
}
|
||
|
||
.boot-logo {
|
||
font-family: 'Orbitron', sans-serif;
|
||
font-size: 3rem;
|
||
font-weight: 900;
|
||
color: var(--neon-pink);
|
||
text-shadow: 0 0 10px var(--neon-pink), 0 0 20px var(--neon-pink), 0 0 40px var(--neon-pink);
|
||
margin-bottom: 20px;
|
||
animation: flicker 2s infinite;
|
||
}
|
||
|
||
.boot-text {
|
||
color: var(--neon-cyan);
|
||
font-size: 0.9rem;
|
||
letter-spacing: 2px;
|
||
margin-top: 10px;
|
||
}
|
||
|
||
.boot-progress {
|
||
width: 300px;
|
||
height: 4px;
|
||
background: rgba(255, 255, 255, 0.1);
|
||
margin-top: 30px;
|
||
position: relative;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.boot-progress-bar {
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
height: 100%;
|
||
width: 0%;
|
||
background: var(--neon-blue);
|
||
box-shadow: 0 0 10px var(--neon-blue);
|
||
animation: bootProgress 3s ease forwards;
|
||
}
|
||
|
||
@keyframes bootProgress {
|
||
to { width: 100%; }
|
||
}
|
||
|
||
@keyframes flicker {
|
||
0%, 19%, 21%, 23%, 25%, 54%, 56%, 100% { opacity: 1; }
|
||
20%, 24%, 55% { opacity: 0.4; }
|
||
}
|
||
|
||
/* 锁屏界面 */
|
||
#lock-screen {
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
width: 100%;
|
||
height: 100%;
|
||
background: rgba(13, 13, 22, 0.95);
|
||
backdrop-filter: blur(10px);
|
||
display: none;
|
||
flex-direction: column;
|
||
justify-content: center;
|
||
align-items: center;
|
||
z-index: 9000;
|
||
}
|
||
|
||
.lock-Time {
|
||
font-family: 'Orbitron', sans-serif;
|
||
font-size: 5rem;
|
||
color: var(--neon-pink);
|
||
text-shadow: 0 0 20px var(--neon-pink);
|
||
margin-bottom: 20px;
|
||
}
|
||
|
||
.lock-Date {
|
||
font-size: 1.5rem;
|
||
color: var(--neon-cyan);
|
||
margin-bottom: 30px;
|
||
}
|
||
|
||
.lock-input {
|
||
background: rgba(5, 217, 232, 0.1);
|
||
border: 1px solid var(--neon-blue);
|
||
color: var(--neon-blue);
|
||
padding: 12px 20px;
|
||
font-family: 'Roboto Mono', monospace;
|
||
font-size: 1rem;
|
||
width: 300px;
|
||
text-align: center;
|
||
outline: none;
|
||
transition: all 0.3s;
|
||
border-radius: 4px;
|
||
}
|
||
|
||
.lock-input:focus {
|
||
box-shadow: 0 0 15px var(--neon-blue);
|
||
background: rgba(5, 217, 232, 0.2);
|
||
}
|
||
|
||
.lock-buttons {
|
||
margin-top: 20px;
|
||
display: flex;
|
||
gap: 15px;
|
||
}
|
||
|
||
.lock-btn {
|
||
padding: 10px 20px;
|
||
background: rgba(5, 217, 232, 0.1);
|
||
border: 1px solid var(--neon-blue);
|
||
color: var(--neon-blue);
|
||
cursor: pointer;
|
||
border-radius: 4px;
|
||
transition: all 0.2s;
|
||
font-family: 'Roboto Mono', monospace;
|
||
}
|
||
|
||
.lock-btn:hover {
|
||
background: var(--neon-blue);
|
||
color: var(--dark-bg);
|
||
box-shadow: 0 0 15px var(--neon-blue);
|
||
}
|
||
|
||
.lock-hint {
|
||
margin-top: 15px;
|
||
color: var(--neon-purple);
|
||
font-size: 0.8rem;
|
||
cursor: pointer;
|
||
}
|
||
|
||
/* 桌面 - 修复显示问题 */
|
||
#desktop {
|
||
display: none; /* 默认隐藏,通过JS控制显示 */
|
||
width: 100%;
|
||
height: 100%;
|
||
position: relative;
|
||
background: var(--dark-bg);
|
||
}
|
||
|
||
/* 当桌面显示时,覆盖所有内容 */
|
||
#desktop.active {
|
||
display: block !important;
|
||
}
|
||
|
||
/* 桌面小部件 */
|
||
.desktop-widgets {
|
||
position: absolute;
|
||
top: 20px;
|
||
right: 20px;
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 10px;
|
||
z-index: 100;
|
||
}
|
||
|
||
.widget {
|
||
background: var(--glass-bg);
|
||
border: 1px solid var(--glass-border);
|
||
backdrop-filter: blur(10px);
|
||
padding: 15px;
|
||
border-radius: 8px;
|
||
min-width: 200px;
|
||
box-shadow: 0 0 20px rgba(5, 217, 232, 0.2);
|
||
}
|
||
|
||
.widget-title {
|
||
font-family: 'Orbitron', sans-serif;
|
||
font-size: 0.8rem;
|
||
color: var(--neon-cyan);
|
||
margin-bottom: 10px;
|
||
text-transform: uppercase;
|
||
}
|
||
|
||
.widget-content {
|
||
font-size: 0.9rem;
|
||
color: var(--neon-blue);
|
||
}
|
||
|
||
.system-monitor-bars {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 5px;
|
||
margin-top: 10px;
|
||
}
|
||
|
||
.monitor-bar {
|
||
height: 6px;
|
||
background: rgba(255, 255, 255, 0.1);
|
||
border-radius: 3px;
|
||
overflow: hidden;
|
||
position: relative;
|
||
}
|
||
|
||
.monitor-bar-fill {
|
||
height: 100%;
|
||
background: var(--neon-pink);
|
||
box-shadow: 0 0 5px var(--neon-pink);
|
||
transition: width 0.5s ease;
|
||
}
|
||
|
||
/* 桌面图标 */
|
||
.desktop-icons {
|
||
position: absolute;
|
||
top: 20px;
|
||
left: 20px;
|
||
display: grid;
|
||
grid-template-columns: repeat(4, 1fr);
|
||
gap: 20px;
|
||
z-index: 50;
|
||
}
|
||
|
||
.desktop-icon {
|
||
width: 80px;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
cursor: pointer;
|
||
transition: all 0.2s;
|
||
padding: 10px;
|
||
border-radius: 8px;
|
||
}
|
||
|
||
.desktop-icon:hover {
|
||
background: rgba(255, 42, 109, 0.2);
|
||
box-shadow: 0 0 15px var(--neon-pink);
|
||
transform: scale(1.05);
|
||
}
|
||
|
||
.desktop-icon i {
|
||
font-size: 2rem;
|
||
margin-bottom: 5px;
|
||
color: var(--neon-blue);
|
||
text-shadow: 0 0 10px var(--neon-blue);
|
||
}
|
||
|
||
.desktop-icon span {
|
||
font-size: 0.7rem;
|
||
color: var(--neon-cyan);
|
||
text-align: center;
|
||
}
|
||
|
||
/* 任务栏 */
|
||
#taskbar {
|
||
position: absolute;
|
||
bottom: 0;
|
||
left: 0;
|
||
width: 100%;
|
||
height: 50px;
|
||
background: var(--glass-bg);
|
||
backdrop-filter: blur(10px);
|
||
border-top: 1px solid var(--glass-border);
|
||
display: flex;
|
||
align-items: center;
|
||
padding: 0 20px;
|
||
z-index: 8000;
|
||
box-shadow: 0 -5px 20px rgba(0, 0, 0, 0.5);
|
||
}
|
||
|
||
.taskbar-start {
|
||
font-family: 'Orbitron', sans-serif;
|
||
font-weight: 700;
|
||
color: var(--neon-pink);
|
||
cursor: pointer;
|
||
padding: 8px 15px;
|
||
border: 1px solid var(--neon-pink);
|
||
border-radius: 4px;
|
||
transition: all 0.2s;
|
||
margin-right: 20px;
|
||
}
|
||
|
||
.taskbar-start:hover {
|
||
background: var(--neon-pink);
|
||
color: var(--dark-bg);
|
||
box-shadow: 0 0 15px var(--neon-pink);
|
||
}
|
||
|
||
.taskbar-apps {
|
||
display: flex;
|
||
gap: 10px;
|
||
flex-grow: 1;
|
||
}
|
||
|
||
.taskbar-app {
|
||
padding: 8px 15px;
|
||
background: rgba(5, 217, 232, 0.1);
|
||
border: 1px solid rgba(5, 217, 232, 0.3);
|
||
color: var(--neon-blue);
|
||
cursor: pointer;
|
||
border-radius: 4px;
|
||
transition: all 0.2s;
|
||
font-size: 0.8rem;
|
||
}
|
||
|
||
.taskbar-app:hover {
|
||
background: rgba(5, 217, 232, 0.2);
|
||
box-shadow: 0 0 10px rgba(5, 217, 232, 0.3);
|
||
}
|
||
|
||
.taskbar-app.active {
|
||
background: var(--neon-blue);
|
||
color: var(--dark-bg);
|
||
box-shadow: 0 0 15px var(--neon-blue);
|
||
}
|
||
|
||
.taskbar-system {
|
||
display: flex;
|
||
gap: 15px;
|
||
align-items: center;
|
||
}
|
||
|
||
.taskbar-icon {
|
||
color: var(--neon-cyan);
|
||
cursor: pointer;
|
||
transition: all 0.2s;
|
||
}
|
||
|
||
.taskbar-icon:hover {
|
||
color: var(--neon-pink);
|
||
text-shadow: 0 0 10px var(--neon-pink);
|
||
}
|
||
|
||
.taskbar-clock {
|
||
font-family: 'Orbitron', sans-serif;
|
||
color: var(--neon-purple);
|
||
font-size: 0.9rem;
|
||
min-width: 80px;
|
||
text-align: right;
|
||
}
|
||
|
||
/* 开始菜单 */
|
||
#start-menu {
|
||
position: absolute;
|
||
bottom: 50px;
|
||
left: 20px;
|
||
width: 300px;
|
||
background: var(--glass-bg);
|
||
backdrop-filter: blur(15px);
|
||
border: 1px solid var(--glass-border);
|
||
border-radius: 8px;
|
||
padding: 20px;
|
||
display: none;
|
||
z-index: 8500;
|
||
box-shadow: 0 0 30px rgba(5, 217, 232, 0.3);
|
||
}
|
||
|
||
.start-menu-title {
|
||
font-family: 'Orbitron', sans-serif;
|
||
color: var(--neon-pink);
|
||
font-size: 1.2rem;
|
||
margin-bottom: 20px;
|
||
text-align: center;
|
||
}
|
||
|
||
.start-menu-apps {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 8px;
|
||
margin-bottom: 20px;
|
||
}
|
||
|
||
.start-menu-app {
|
||
padding: 10px;
|
||
background: rgba(255, 255, 255, 0.05);
|
||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||
border-radius: 4px;
|
||
cursor: pointer;
|
||
transition: all 0.2s;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 10px;
|
||
}
|
||
|
||
.start-menu-app:hover {
|
||
background: rgba(5, 217, 232, 0.2);
|
||
border-color: var(--neon-blue);
|
||
box-shadow: 0 0 10px rgba(5, 217, 232, 0.3);
|
||
}
|
||
|
||
.start-menu-app i {
|
||
width: 20px;
|
||
text-align: center;
|
||
color: var(--neon-cyan);
|
||
}
|
||
|
||
.start-menu-options {
|
||
border-top: 1px solid rgba(255, 255, 255, 0.1);
|
||
padding-top: 15px;
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 8px;
|
||
}
|
||
|
||
.start-menu-option {
|
||
padding: 8px;
|
||
cursor: pointer;
|
||
border-radius: 4px;
|
||
transition: all 0.2s;
|
||
color: var(--neon-purple);
|
||
text-align: center;
|
||
}
|
||
|
||
.start-menu-option:hover {
|
||
background: rgba(255, 42, 109, 0.2);
|
||
box-shadow: 0 0 10px rgba(255, 42, 109, 0.3);
|
||
color: var(--neon-pink);
|
||
}
|
||
|
||
/* 窗口系统 */
|
||
.window {
|
||
position: absolute;
|
||
background: var(--glass-bg);
|
||
backdrop-filter: blur(15px);
|
||
border: 1px solid var(--glass-border);
|
||
border-radius: 8px 8px 0 0;
|
||
display: flex;
|
||
flex-direction: column;
|
||
min-width: 300px;
|
||
min-height: 200px;
|
||
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
|
||
transition: transform 0.2s, box-shadow 0.2s;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.window.active {
|
||
border-color: var(--neon-blue);
|
||
box-shadow: 0 10px 30px rgba(5, 217, 232, 0.3);
|
||
}
|
||
|
||
.window-header {
|
||
background: rgba(5, 217, 232, 0.1);
|
||
padding: 8px 12px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
cursor: move;
|
||
border-bottom: 1px solid rgba(5, 217, 232, 0.2);
|
||
}
|
||
|
||
.window-title {
|
||
font-family: 'Orbitron', sans-serif;
|
||
font-size: 0.9rem;
|
||
color: var(--neon-blue);
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
}
|
||
|
||
.window-controls {
|
||
display: flex;
|
||
gap: 8px;
|
||
}
|
||
|
||
.window-control {
|
||
width: 12px;
|
||
height: 12px;
|
||
border-radius: 50%;
|
||
cursor: pointer;
|
||
transition: all 0.2s;
|
||
}
|
||
|
||
.window-control.close {
|
||
background: var(--neon-pink);
|
||
box-shadow: 0 0 5px var(--neon-pink);
|
||
}
|
||
|
||
.window-control.minimize {
|
||
background: var(--neon-cyan);
|
||
box-shadow: 0 0 5px var(--neon-cyan);
|
||
}
|
||
|
||
.window-control.maximize {
|
||
background: var(--neon-purple);
|
||
box-shadow: 0 0 5px var(--neon-purple);
|
||
}
|
||
|
||
.window-control:hover {
|
||
transform: scale(1.2);
|
||
}
|
||
|
||
.window-body {
|
||
flex: 1;
|
||
padding: 15px;
|
||
overflow: auto;
|
||
color: var(--neon-blue);
|
||
}
|
||
|
||
.window-resize {
|
||
position: absolute;
|
||
right: 0;
|
||
bottom: 0;
|
||
width: 20px;
|
||
height: 20px;
|
||
cursor: nwse-resize;
|
||
background: linear-gradient(135deg, transparent 50%, var(--neon-blue) 50%);
|
||
opacity: 0.5;
|
||
}
|
||
|
||
/* 终端 */
|
||
.terminal {
|
||
font-family: 'Roboto Mono', monospace;
|
||
background: rgba(0, 0, 0, 0.7);
|
||
height: 100%;
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
|
||
.terminal-output {
|
||
flex: 1;
|
||
padding: 10px;
|
||
overflow-y: auto;
|
||
white-space: pre-wrap;
|
||
font-size: 0.9rem;
|
||
line-height: 1.4;
|
||
}
|
||
|
||
.terminal-input-line {
|
||
display: flex;
|
||
padding: 10px;
|
||
background: rgba(5, 217, 232, 0.1);
|
||
}
|
||
|
||
.terminal-prompt {
|
||
color: var(--neon-green);
|
||
margin-right: 8px;
|
||
}
|
||
|
||
.terminal-input {
|
||
background: transparent;
|
||
border: none;
|
||
outline: none;
|
||
color: var(--neon-blue);
|
||
flex: 1;
|
||
font-family: 'Roboto Mono', monospace;
|
||
font-size: 0.9rem;
|
||
}
|
||
|
||
.terminal .green { color: var(--neon-cyan); }
|
||
.terminal .pink { color: var(--neon-pink); }
|
||
.terminal .purple { color: var(--neon-purple); }
|
||
.terminal .error { color: #ff5555; }
|
||
|
||
/* 通知系统 */
|
||
#notification-area {
|
||
position: absolute;
|
||
top: 20px;
|
||
right: 20px;
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 10px;
|
||
width: 300px;
|
||
z-index: 9500;
|
||
}
|
||
|
||
.notification {
|
||
background: var(--glass-bg);
|
||
backdrop-filter: blur(15px);
|
||
border: 1px solid var(--glass-border);
|
||
border-radius: 8px;
|
||
padding: 15px;
|
||
animation: slideIn 0.3s ease;
|
||
box-shadow: 0 5px 20px rgba(0, 0, 0, 0.3);
|
||
position: relative;
|
||
overflow: hidden;
|
||
}
|
||
|
||
@keyframes slideIn {
|
||
from {
|
||
transform: translateX(100%);
|
||
opacity: 0;
|
||
}
|
||
to {
|
||
transform: translateX(0);
|
||
opacity: 1;
|
||
}
|
||
}
|
||
|
||
.notification-header {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
margin-bottom: 8px;
|
||
align-items: center;
|
||
}
|
||
|
||
.notification-title {
|
||
font-family: 'Orbitron', sans-serif;
|
||
font-size: 0.9rem;
|
||
color: var(--neon-pink);
|
||
}
|
||
|
||
.notification-close {
|
||
cursor: pointer;
|
||
color: var(--neon-cyan);
|
||
opacity: 0.7;
|
||
}
|
||
|
||
.notification-close:hover {
|
||
opacity: 1;
|
||
color: var(--neon-pink);
|
||
}
|
||
|
||
.notification-body {
|
||
font-size: 0.8rem;
|
||
color: var(--neon-blue);
|
||
line-height: 1.4;
|
||
}
|
||
|
||
.notification.success { border-left: 3px solid var(--neon-cyan); }
|
||
.notification.error { border-left: 3px solid #ff5555; }
|
||
.notification.warning { border-left: 3px solid #ffaa00; }
|
||
.notification.info { border-left: 3px solid var(--neon-blue); }
|
||
|
||
/* 右键菜单 */
|
||
#context-menu {
|
||
position: absolute;
|
||
background: var(--glass-bg);
|
||
backdrop-filter: blur(15px);
|
||
border: 1px solid var(--glass-border);
|
||
border-radius: 8px;
|
||
padding: 8px 0;
|
||
display: none;
|
||
z-index: 10000;
|
||
min-width: 180px;
|
||
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
|
||
}
|
||
|
||
.context-menu-item {
|
||
padding: 10px 15px;
|
||
cursor: pointer;
|
||
transition: all 0.2s;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 10px;
|
||
color: var(--neon-blue);
|
||
font-size: 0.9rem;
|
||
}
|
||
|
||
.context-menu-item:hover {
|
||
background: rgba(5, 217, 232, 0.2);
|
||
color: var(--neon-cyan);
|
||
}
|
||
|
||
.context-menu-item i {
|
||
width: 20px;
|
||
text-align: center;
|
||
}
|
||
|
||
.context-menu-divider {
|
||
height: 1px;
|
||
background: rgba(255, 255, 255, 0.1);
|
||
margin: 5px 0;
|
||
}
|
||
|
||
/* 矩阵雨画布 */
|
||
#matrix-canvas {
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
width: 100%;
|
||
height: 100%;
|
||
z-index: 9999;
|
||
display: none;
|
||
background: black;
|
||
}
|
||
|
||
/* 隐藏类 - 用于灵活控制 */
|
||
.hidden {
|
||
display: none !important;
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<!-- 开机动画 -->
|
||
<div id="boot-screen">
|
||
<div class="boot-logo">NEON-OS</div>
|
||
<div class="boot-text">初始化系统核心模块...</div>
|
||
<div class="boot-progress">
|
||
<div class="boot-progress-bar"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 锁屏界面 -->
|
||
<div id="lock-screen">
|
||
<div class="lock-Time" id="lock-time">00:00</div>
|
||
<div class="lock-Date" id="lock-date">加载中...</div>
|
||
<input type="password" class="lock-input" placeholder="输入密码或点击跳过" id="lock-password">
|
||
<div class="lock-buttons">
|
||
<button class="lock-btn" onclick="unlockSystem()">进入系统</button>
|
||
<button class="lock-btn" onclick="skipLockScreen()">跳过</button>
|
||
</div>
|
||
<div class="lock-hint">提示:直接点击"跳过"即可进入</div>
|
||
</div>
|
||
|
||
<!-- 桌面 -->
|
||
<div id="desktop" style="display:none;">
|
||
<div class="desktop-bg"></div>
|
||
<div class="scan-lines"></div>
|
||
|
||
<!-- 桌面小部件 -->
|
||
<div class="desktop-widgets">
|
||
<div class="widget">
|
||
<div class="widget-title">系统时钟</div>
|
||
<div class="widget-content" id="widget-clock">00:00:00</div>
|
||
</div>
|
||
<div class="widget">
|
||
<div class="widget-title">系统状态</div>
|
||
<div class="widget-content" id="widget-status">运行中</div>
|
||
<div class="system-monitor-bars">
|
||
<div class="monitor-bar">
|
||
<div class="monitor-bar-fill" id="cpu-bar" style="width: 45%"></div>
|
||
</div>
|
||
<div class="monitor-bar">
|
||
<div class="monitor-bar-fill" id="mem-bar" style="width: 62%"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="widget">
|
||
<div class="widget-title">快速命令</div>
|
||
<div class="widget-content" style="cursor: pointer; padding: 5px;">
|
||
<div style="margin: 5px 0;" onclick="openTerminal()">打开终端</div>
|
||
<div style="margin: 5px 0;" onclick="showNotification('info', '系统信息', 'NEON-OS 版本 1.0.0')">系统信息</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 桌面图标 -->
|
||
<div class="desktop-icons">
|
||
<div class="desktop-icon" onclick="openApp('file-manager')">
|
||
<i class="fas fa-folder"></i>
|
||
<span>文件管理器</span>
|
||
</div>
|
||
<div class="desktop-icon" onclick="openTerminal()">
|
||
<i class="fas fa-terminal"></i>
|
||
<span>终端</span>
|
||
</div>
|
||
<div class="desktop-icon" onclick="openApp('browser')">
|
||
<i class="fas fa-globe"></i>
|
||
<span>浏览器</span>
|
||
</div>
|
||
<div class="desktop-icon" onclick="openApp('settings')">
|
||
<i class="fas fa-cog"></i>
|
||
<span>设置中心</span>
|
||
</div>
|
||
<div class="desktop-icon" onclick="openApp('music-player')">
|
||
<i class="fas fa-music"></i>
|
||
<span>音乐播放器</span>
|
||
</div>
|
||
<div class="desktop-icon" onclick="openApp('notepad')">
|
||
<i class="fas fa-sticky-note"></i>
|
||
<span>便签</span>
|
||
</div>
|
||
<div class="desktop-icon" onclick="openApp('monitor')">
|
||
<i class="fas fa-chart-line"></i>
|
||
<span>系统监控</span>
|
||
</div>
|
||
<div class="desktop-icon" onclick="openApp('about')">
|
||
<i class="fas fa-info-circle"></i>
|
||
<span>关于系统</span>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 任务栏 -->
|
||
<div id="taskbar">
|
||
<div class="taskbar-start" onclick="toggleStartMenu()">
|
||
<i class="fas fa-power-off"></i> 开始
|
||
</div>
|
||
<div class="taskbar-apps" id="taskbar-apps"></div>
|
||
<div class="taskbar-system">
|
||
<i class="fas fa-bell taskbar-icon" onclick="showNotification('info', '通知中心', '暂无新通知')"></i>
|
||
<i class="fas fa-volume-up taskbar-icon" onclick="toggleVolume()"></i>
|
||
<div class="taskbar-clock" id="taskbar-clock">00:00</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 开始菜单 -->
|
||
<div id="start-menu">
|
||
<div class="user-avatar">NE</div>
|
||
<div class="start-menu-title">NEON-OS</div>
|
||
<div class="start-menu-apps">
|
||
<div class="start-menu-app" onclick="openApp('file-manager')">
|
||
<i class="fas fa-folder"></i> 文件管理器
|
||
</div>
|
||
<div class="start-menu-app" onclick="openTerminal()">
|
||
<i class="fas fa-terminal"></i> 终端
|
||
</div>
|
||
<div class="start-menu-app" onclick="openApp('browser')">
|
||
<i class="fas fa-globe"></i> 浏览器
|
||
</div>
|
||
<div class="start-menu-app" onclick="openApp('settings')">
|
||
<i class="fas fa-cog"></i> 设置中心
|
||
</div>
|
||
</div>
|
||
<div class="start-menu-options">
|
||
<div class="start-menu-option" onclick="rebootSystem()">重启系统</div>
|
||
<div class="start-menu-option" onclick="logout()">切换用户</div>
|
||
<div class="start-menu-option" onclick="shutdown()">关机</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 通知区域 -->
|
||
<div id="notification-area"></div>
|
||
|
||
<!-- 右键菜单 -->
|
||
<div id="context-menu">
|
||
<div class="context-menu-item" onclick="refreshDesktop()">
|
||
<i class="fas fa-sync-alt"></i> 刷新
|
||
</div>
|
||
<div class="context-menu-item" onclick="openApp('settings')">
|
||
<i class="fas fa-cog"></i> 个性化设置
|
||
</div>
|
||
<div class="context-menu-divider"></div>
|
||
<div class="context-menu-item" onclick="openApp('about')">
|
||
<i class="fas fa-info-circle"></i> 关于 NEON-OS
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 矩阵雨画布 -->
|
||
<canvas id="matrix-canvas"></canvas>
|
||
</div>
|
||
|
||
<script>
|
||
// 全局状态管理
|
||
const state = {
|
||
apps: {},
|
||
nextZIndex: 100,
|
||
settings: {
|
||
theme: 'cyberpunk',
|
||
volume: 0.7,
|
||
wallpaper: 'default',
|
||
notifications: true
|
||
},
|
||
fileSystem: {
|
||
root: {
|
||
type: 'folder',
|
||
children: {
|
||
'Documents': {
|
||
type: 'folder',
|
||
children: {
|
||
'readme.txt': { type: 'file', content: '欢迎使用 NEON-OS!\n这是一个赛博朋克风格的操作系统。\n尝试在终端输入 help 查看可用命令。' },
|
||
'notes.txt': { type: 'file', content: '我的笔记:\n- 优化render循环\n- 修复拖拽bug\n- 添加更多命令' }
|
||
}
|
||
},
|
||
'Projects': {
|
||
type: 'folder',
|
||
children: {
|
||
'neon-os.html': { type: 'file', content: '<!DOCTYPE html>\n<!-- 这是我们之前的工作 -->' },
|
||
'design.fig': { type: 'file', content: '二进制文件预览:\n[FIGMA设计原型数据]' }
|
||
}
|
||
},
|
||
'Music': {
|
||
type: 'folder',
|
||
children: {
|
||
'synthwave.mp3': { type: 'file', content: '音频文件' },
|
||
'cyberpunk.flac': { type: 'file', content: '无损音频' }
|
||
}
|
||
},
|
||
'config.json': { type: 'file', content: '{\n "theme": "cyberpunk",\n "notifications": true\n}' }
|
||
}
|
||
}
|
||
},
|
||
currentDirectory: [],
|
||
musicPlayer: {
|
||
playing: false,
|
||
currentTrack: 0,
|
||
tracks: [
|
||
{ title: '霓虹之夜', artist: 'SynthWave', duration: 180 },
|
||
{ title: '数字梦境', artist: 'CyberPunk', duration: 220 },
|
||
{ title: '未来都市', artist: 'NeoTokyo', duration: 200 }
|
||
]
|
||
},
|
||
terminalHistory: [],
|
||
matrixRunning: false
|
||
};
|
||
|
||
// 初始化系统
|
||
function initSystem() {
|
||
console.log('[SYSTEM] 正在初始化...');
|
||
const savedSettings = localStorage.getItem('neon-os-settings');
|
||
if (savedSettings) {
|
||
try {
|
||
const parsed = JSON.parse(savedSettings);
|
||
state.settings = { ...state.settings, ...parsed };
|
||
console.log('[SYSTEM] 设置已加载');
|
||
} catch (e) {
|
||
console.log('[SYSTEM] 设置加载失败,使用默认值');
|
||
}
|
||
}
|
||
|
||
setTimeout(() => {
|
||
const bootScreen = document.getElementById('boot-screen');
|
||
if (bootScreen) {
|
||
bootScreen.style.opacity = '0';
|
||
setTimeout(() => {
|
||
bootScreen.style.display = 'none';
|
||
showLockScreen();
|
||
}, 500);
|
||
}
|
||
}, 2000); // 缩短开机动画时间,加快测试
|
||
}
|
||
|
||
// 显示锁屏
|
||
function showLockScreen() {
|
||
console.log('[LOCK] 显示锁屏界面');
|
||
const lockScreen = document.getElementById('lock-screen');
|
||
if (lockScreen) {
|
||
lockScreen.style.display = 'flex';
|
||
}
|
||
|
||
updateLockTime();
|
||
setInterval(updateLockTime, 1000);
|
||
|
||
const passwordInput = document.getElementById('lock-password');
|
||
const hint = document.querySelector('.lock-hint');
|
||
|
||
if (passwordInput) {
|
||
passwordInput.addEventListener('keydown', (e) => {
|
||
if (e.key === 'Enter') {
|
||
unlockSystem();
|
||
}
|
||
});
|
||
}
|
||
|
||
if (hint) {
|
||
hint.addEventListener('click', skipLockScreen);
|
||
}
|
||
}
|
||
|
||
function updateLockTime() {
|
||
const now = new Date();
|
||
const hours = String(now.getHours()).padStart(2, '0');
|
||
const minutes = String(now.getMinutes()).padStart(2, '0');
|
||
const seconds = String(now.getSeconds()).padStart(2, '0');
|
||
const timeStr = `${hours}:${minutes}:${seconds}`;
|
||
|
||
const dateStr = now.toLocaleDateString('zh-CN', {
|
||
year: 'numeric',
|
||
month: 'long',
|
||
day: 'numeric',
|
||
weekday: 'long'
|
||
});
|
||
|
||
const lockTime = document.getElementById('lock-time');
|
||
const lockDate = document.getElementById('lock-date');
|
||
|
||
if (lockTime) lockTime.textContent = timeStr;
|
||
if (lockDate) lockDate.textContent = dateStr;
|
||
|
||
const taskbarClock = document.getElementById('taskbar-clock');
|
||
if (taskbarClock) {
|
||
taskbarClock.textContent = `${hours}:${minutes}`;
|
||
}
|
||
|
||
const widgetClock = document.getElementById('widget-clock');
|
||
if (widgetClock) {
|
||
widgetClock.textContent = timeStr;
|
||
}
|
||
}
|
||
|
||
// 跳过锁屏(直接进入)
|
||
function skipLockScreen() {
|
||
console.log('[LOCK] 跳过锁屏,直接进入系统');
|
||
unlockSystem();
|
||
}
|
||
|
||
// 解锁系统 - 修复显示问题
|
||
function unlockSystem() {
|
||
console.log('[UNLOCK] 开始解锁流程');
|
||
const lockScreen = document.getElementById('lock-screen');
|
||
const desktop = document.getElementById('desktop');
|
||
|
||
if (!lockScreen || !desktop) {
|
||
console.error('[UNLOCK] 必要元素未找到');
|
||
return;
|
||
}
|
||
|
||
// 简化解锁流程
|
||
lockScreen.style.opacity = '0';
|
||
console.log('[UNLOCK] 锁屏透明度设置为0');
|
||
|
||
setTimeout(() => {
|
||
console.log('[UNLOCK] 隐藏锁屏,显示桌面');
|
||
lockScreen.style.display = 'none';
|
||
|
||
// 显示桌面 - 使用多种方式确保显示
|
||
desktop.style.display = 'block';
|
||
desktop.classList.remove('hidden');
|
||
desktop.classList.add('active');
|
||
|
||
console.log('[UNLOCK] 桌面display样式:', desktop.style.display);
|
||
console.log('[UNLOCK] 桌面classList:', desktop.className);
|
||
|
||
// 启动桌面动画
|
||
try {
|
||
startDesktopAnimation();
|
||
console.log('[UNLOCK] 桌面动画已启动');
|
||
} catch (e) {
|
||
console.error('[UNLOCK] 桌面动画启动失败:', e);
|
||
}
|
||
|
||
// 显示欢迎通知
|
||
setTimeout(() => {
|
||
showNotification('success', '系统启动', '欢迎回来,用户');
|
||
console.log('[UNLOCK] 已显示欢迎通知');
|
||
}, 500);
|
||
|
||
setTimeout(() => {
|
||
showNotification('info', '提示', '右键点击桌面访问菜单,或使用开始菜单打开应用');
|
||
}, 3000);
|
||
|
||
}, 500);
|
||
}
|
||
|
||
// 桌面动画
|
||
function startDesktopAnimation() {
|
||
console.log('[ANIM] 开始桌面监控动画');
|
||
|
||
// CPU/内存监控
|
||
setInterval(() => {
|
||
if (!document.getElementById('desktop') || document.getElementById('desktop').style.display === 'none') return;
|
||
|
||
const cpu = Math.floor(Math.random() * 30) + 20;
|
||
const mem = Math.floor(Math.random() * 30) + 40;
|
||
|
||
const cpuBar = document.getElementById('cpu-bar');
|
||
const memBar = document.getElementById('mem-bar');
|
||
|
||
if (cpuBar) cpuBar.style.width = cpu + '%';
|
||
if (memBar) memBar.style.width = mem + '%';
|
||
}, 2000);
|
||
|
||
// 随机通知
|
||
setInterval(() => {
|
||
if (!document.getElementById('desktop') || document.getElementById('desktop').style.display === 'none') return;
|
||
|
||
if (Math.random() > 0.9 && state.settings.notifications) {
|
||
const messages = [
|
||
{ type: 'info', title: '系统更新', msg: '检查到可用的系统更新' },
|
||
{ type: 'success', title: '备份完成', msg: '所有文件已自动备份' },
|
||
{ type: 'warning', title: '磁盘空间', msg: 'C盘剩余空间不足20%' }
|
||
];
|
||
const msg = messages[Math.floor(Math.random() * messages.length)];
|
||
showNotification(msg.type, msg.title, msg.msg);
|
||
}
|
||
}, 15000);
|
||
}
|
||
|
||
// 窗口管理系统(保持原有逻辑,略作简化)
|
||
function createWindow(appId, title, icon, initialContent = '') {
|
||
if (state.apps[appId]) {
|
||
activateWindow(appId);
|
||
return;
|
||
}
|
||
|
||
const window = document.createElement('div');
|
||
window.className = 'window';
|
||
window.id = `window-${appId}`;
|
||
window.style.left = '100px';
|
||
window.style.top = '100px';
|
||
window.style.width = '600px';
|
||
window.style.height = '400px';
|
||
window.style.zIndex = state.nextZIndex++;
|
||
|
||
window.innerHTML = `
|
||
<div class="window-header" data-app="${appId}">
|
||
<div class="window-title">
|
||
<i class="${icon}"></i>
|
||
<span>${title}</span>
|
||
</div>
|
||
<div class="window-controls">
|
||
<div class="window-control minimize" onclick="minimizeWindow('${appId}')"></div>
|
||
<div class="window-control maximize" onclick="maximizeWindow('${appId}')"></div>
|
||
<div class="window-control close" onclick="closeWindow('${appId}')"></div>
|
||
</div>
|
||
</div>
|
||
<div class="window-body" id="body-${appId}">
|
||
${initialContent}
|
||
</div>
|
||
<div class="window-resize" data-app="${appId}"></div>
|
||
`;
|
||
|
||
document.getElementById('desktop').appendChild(window);
|
||
|
||
state.apps[appId] = {
|
||
element: window,
|
||
minimized: false,
|
||
maximized: false,
|
||
originalSize: { width: '600px', height: '400px', left: '100px', top: '100px' }
|
||
};
|
||
|
||
makeDraggable(window);
|
||
makeResizable(window);
|
||
activateWindow(appId);
|
||
addToTaskbar(appId, title, icon);
|
||
}
|
||
|
||
function makeDraggable(element) {
|
||
const header = element.querySelector('.window-header');
|
||
let isDragging = false;
|
||
let currentX, currentY, initialX, initialY;
|
||
|
||
header.addEventListener('mousedown', (e) => {
|
||
if (e.target.classList.contains('window-control')) return;
|
||
isDragging = true;
|
||
initialX = e.clientX - element.offsetLeft;
|
||
initialY = e.clientY - element.offsetTop;
|
||
activateWindow(element.id.replace('window-', ''));
|
||
e.preventDefault();
|
||
});
|
||
|
||
document.addEventListener('mousemove', (e) => {
|
||
if (!isDragging) return;
|
||
currentX = e.clientX - initialX;
|
||
currentY = e.clientY - initialY;
|
||
currentX = Math.max(0, Math.min(currentX, window.innerWidth - element.offsetWidth));
|
||
currentY = Math.max(0, Math.min(currentY, window.innerHeight - 50));
|
||
element.style.left = currentX + 'px';
|
||
element.style.top = currentY + 'px';
|
||
});
|
||
|
||
document.addEventListener('mouseup', () => { isDragging = false; });
|
||
}
|
||
|
||
function makeResizable(element) {
|
||
const resizeHandle = element.querySelector('.window-resize');
|
||
let isResizing = false;
|
||
let startX, startY, startWidth, startHeight;
|
||
|
||
resizeHandle.addEventListener('mousedown', (e) => {
|
||
isResizing = true;
|
||
startX = e.clientX;
|
||
startY = e.clientY;
|
||
startWidth = element.offsetWidth;
|
||
startHeight = element.offsetHeight;
|
||
e.preventDefault();
|
||
});
|
||
|
||
document.addEventListener('mousemove', (e) => {
|
||
if (!isResizing) return;
|
||
const newWidth = startWidth + (e.clientX - startX);
|
||
const newHeight = startHeight + (e.clientY - startY);
|
||
if (newWidth > 300) element.style.width = newWidth + 'px';
|
||
if (newHeight > 200) element.style.height = newHeight + 'px';
|
||
});
|
||
|
||
document.addEventListener('mouseup', () => { isResizing = false; });
|
||
}
|
||
|
||
function activateWindow(appId) {
|
||
const app = state.apps[appId];
|
||
if (!app) return;
|
||
|
||
app.element.style.zIndex = state.nextZIndex++;
|
||
Object.values(state.apps).forEach(appItem => appItem.element.classList.remove('active'));
|
||
app.element.classList.add('active');
|
||
|
||
if (app.minimized) {
|
||
app.element.style.display = 'flex';
|
||
app.minimized = false;
|
||
updateTaskbarActive(appId);
|
||
}
|
||
}
|
||
|
||
function minimizeWindow(appId) {
|
||
const app = state.apps[appId];
|
||
if (!app) return;
|
||
app.element.style.display = 'none';
|
||
app.minimized = true;
|
||
updateTaskbarActive(appId);
|
||
}
|
||
|
||
function maximizeWindow(appId) {
|
||
const app = state.apps[appId];
|
||
if (!app) return;
|
||
|
||
if (app.maximized) {
|
||
app.element.style.width = app.originalSize.width;
|
||
app.element.style.height = app.originalSize.height;
|
||
app.element.style.left = app.originalSize.left;
|
||
app.element.style.top = app.originalSize.top;
|
||
app.maximized = false;
|
||
} else {
|
||
app.originalSize = {
|
||
width: app.element.style.width,
|
||
height: app.element.style.height,
|
||
left: app.element.style.left,
|
||
top: app.element.style.top
|
||
};
|
||
app.element.style.width = '100%';
|
||
app.element.style.height = 'calc(100% - 50px)';
|
||
app.element.style.left = '0';
|
||
app.element.style.top = '0';
|
||
app.maximized = true;
|
||
const body = document.getElementById(`body-${appId}`);
|
||
if (body) body.style.height = 'calc(100% - 41px)';
|
||
}
|
||
activateWindow(appId);
|
||
}
|
||
|
||
function closeWindow(appId) {
|
||
const app = state.apps[appId];
|
||
if (!app) return;
|
||
|
||
if (appId === 'music-player' && state.musicPlayer.playing) {
|
||
state.musicPlayer.playing = false;
|
||
stopMusicProgress();
|
||
}
|
||
|
||
if (appId === 'monitor') {
|
||
stopMonitorCharts();
|
||
}
|
||
|
||
app.element.remove();
|
||
delete state.apps[appId];
|
||
removeFromTaskbar(appId);
|
||
}
|
||
|
||
// 任务栏管理
|
||
function addToTaskbar(appId, title, icon) {
|
||
const taskbarApps = document.getElementById('taskbar-apps');
|
||
const appButton = document.createElement('div');
|
||
appButton.className = 'taskbar-app';
|
||
appButton.id = `taskbar-${appId}`;
|
||
appButton.innerHTML = `<i class="${icon}"></i> ${title}`;
|
||
appButton.onclick = () => {
|
||
if (state.apps[appId].minimized) {
|
||
activateWindow(appId);
|
||
} else {
|
||
minimizeWindow(appId);
|
||
}
|
||
};
|
||
taskbarApps.appendChild(appButton);
|
||
updateTaskbarActive(appId);
|
||
}
|
||
|
||
function removeFromTaskbar(appId) {
|
||
const button = document.getElementById(`taskbar-${appId}`);
|
||
if (button) button.remove();
|
||
}
|
||
|
||
function updateTaskbarActive(appId) {
|
||
const buttons = document.querySelectorAll('.taskbar-app');
|
||
buttons.forEach(btn => btn.classList.remove('active'));
|
||
|
||
if (state.apps[appId] && !state.apps[appId].minimized) {
|
||
const activeButton = document.getElementById(`taskbar-${appId}`);
|
||
if (activeButton) activeButton.classList.add('active');
|
||
}
|
||
}
|
||
|
||
// 应用程序逻辑
|
||
function openApp(appId) {
|
||
switch(appId) {
|
||
case 'file-manager': openFileManager(); break;
|
||
case 'browser': openBrowser(); break;
|
||
case 'settings': openSettings(); break;
|
||
case 'music-player': openMusicPlayer(); break;
|
||
case 'notepad': openNotepad(); break;
|
||
case 'monitor': openMonitor(); break;
|
||
case 'about': openAbout(); break;
|
||
}
|
||
}
|
||
|
||
function openTerminal() {
|
||
if (state.apps['terminal']) {
|
||
activateWindow('terminal');
|
||
return;
|
||
}
|
||
|
||
const initialContent = `
|
||
<div class="terminal">
|
||
<div class="terminal-output" id="terminal-output"></div>
|
||
<div class="terminal-input-line">
|
||
<span class="terminal-prompt">user@neon-os:~$</span>
|
||
<input type="text" class="terminal-input" id="terminal-input" placeholder="输入 help 查看可用命令">
|
||
</div>
|
||
</div>
|
||
`;
|
||
|
||
createWindow('terminal', '终端模拟器', 'fas fa-terminal', initialContent);
|
||
|
||
setTimeout(() => {
|
||
const input = document.getElementById('terminal-input');
|
||
const output = document.getElementById('terminal-output');
|
||
|
||
if (output) {
|
||
output.innerHTML = `
|
||
<span class="green">NEON-OS 终端模拟器 v1.0</span>
|
||
<br><span class="purple">输入 'help' 查看可用命令</span>
|
||
<br>
|
||
`;
|
||
}
|
||
|
||
if (input) {
|
||
input.addEventListener('keydown', (e) => {
|
||
if (e.key === 'Enter') {
|
||
const command = input.value.trim();
|
||
if (command) {
|
||
state.terminalHistory.push(command);
|
||
executeCommand(command, output);
|
||
input.value = '';
|
||
output.scrollTop = output.scrollHeight;
|
||
}
|
||
} else if (e.key === 'ArrowUp') {
|
||
if (state.terminalHistory.length > 0) {
|
||
input.value = state.terminalHistory[state.terminalHistory.length - 1];
|
||
}
|
||
}
|
||
});
|
||
input.focus();
|
||
}
|
||
}, 100);
|
||
}
|
||
|
||
function executeCommand(command, output) {
|
||
const parts = command.split(' ');
|
||
const cmd = parts[0].toLowerCase();
|
||
const args = parts.slice(1);
|
||
|
||
const prompt = document.createElement('div');
|
||
prompt.innerHTML = `<span class="terminal-prompt">user@neon-os:~$</span> ${command}`;
|
||
output.appendChild(prompt);
|
||
|
||
let response = '';
|
||
|
||
switch(cmd) {
|
||
case 'help':
|
||
response = '可用命令:\nhelp - 显示此帮助信息\nclear - 清屏\ndate - 显示当前日期时间\nwhoami - 显示当前用户\nls - 列出文件\ncd - 切换目录\ncat - 查看文件内容\necho - 输出文本\nneofetch - 显示系统信息\nmatrix - 启动矩阵雨特效\ntheme - 切换主题\nreboot - 重启系统\nexit - 关闭终端';
|
||
break;
|
||
case 'clear':
|
||
output.innerHTML = '';
|
||
return;
|
||
case 'date':
|
||
response = new Date().toString();
|
||
break;
|
||
case 'whoami':
|
||
response = 'user@neon-os';
|
||
break;
|
||
case 'ls':
|
||
const currentDir = getCurrentDirectory();
|
||
if (typeof currentDir === 'object') {
|
||
response = Object.keys(currentDir.children).map(name => {
|
||
const item = currentDir.children[name];
|
||
return item.type === 'folder' ? `<span class="green">${name}/</span>` : name;
|
||
}).join(' ');
|
||
} else {
|
||
response = '<span class="error">错误:无法读取目录</span>';
|
||
}
|
||
break;
|
||
case 'cd':
|
||
if (args.length === 0) {
|
||
state.currentDirectory = [];
|
||
response = '已返回根目录';
|
||
} else if (args[0] === '..') {
|
||
if (state.currentDirectory.length > 0) {
|
||
state.currentDirectory.pop();
|
||
response = '已返回上级目录';
|
||
} else {
|
||
response = '已在根目录';
|
||
}
|
||
} else {
|
||
const currentDir = getCurrentDirectory();
|
||
if (currentDir.children && currentDir.children[args[0]] && currentDir.children[args[0]].type === 'folder') {
|
||
state.currentDirectory.push(args[0]);
|
||
response = `已切换到 /${state.currentDirectory.join('/')}`;
|
||
} else {
|
||
response = `<span class="error">目录不存在: ${args[0]}</span>`;
|
||
}
|
||
}
|
||
break;
|
||
case 'cat':
|
||
if (args.length === 0) {
|
||
response = '<span class="error">用法: cat <文件名></span>';
|
||
} else {
|
||
const currentDir = getCurrentDirectory();
|
||
if (currentDir.children && currentDir.children[args[0]] && currentDir.children[args[0]].type === 'file') {
|
||
const content = currentDir.children[args[0]].content;
|
||
response = `<pre>${content}</pre>`;
|
||
} else {
|
||
response = `<span class="error">文件不存在: ${args[0]}</span>`;
|
||
}
|
||
}
|
||
break;
|
||
case 'echo':
|
||
response = args.join(' ');
|
||
break;
|
||
case 'neofetch':
|
||
response = '<span style="color: #ff2a6d; font-weight: bold;">NEON-OS</span> 版本 1.0.0\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n<span style="color: #05d9e8;">内核</span>: CyberKernel 2.6.18\n<span style="color: #d100d1;">架构</span>: WebAssembly x86_64\n<span style="color: #00ff9f;">Shell</span>: NeonTerminal v1.0\n<span style="color: #ff2a6d;">主题</span>: ' + state.settings.theme + '\n<span style="color: #05d9e8;">内存占用</span>: ' + (Math.floor(Math.random() * 30 + 20)) + '% / 16GB\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━';
|
||
break;
|
||
case 'matrix':
|
||
if (!state.matrixRunning) {
|
||
startMatrixRain();
|
||
response = '<span class="green">矩阵雨已启动... 输入任意命令或刷新页面退出</span>';
|
||
} else {
|
||
response = '<span class="error">矩阵雨已在运行</span>';
|
||
}
|
||
break;
|
||
case 'theme':
|
||
const themes = ['cyberpunk', 'retro', 'minimal', 'dark', 'light'];
|
||
const nextTheme = themes[(themes.indexOf(state.settings.theme) + 1) % themes.length];
|
||
state.settings.theme = nextTheme;
|
||
saveSettings();
|
||
applyTheme();
|
||
response = '<span class="green">主题已切换至: ' + nextTheme + '</span>';
|
||
break;
|
||
case 'reboot':
|
||
response = '<span class="purple">系统将在3秒后重启...</span>';
|
||
setTimeout(rebootSystem, 3000);
|
||
break;
|
||
case 'exit':
|
||
closeWindow('terminal');
|
||
return;
|
||
case 'mkdir':
|
||
case 'touch':
|
||
case 'rm':
|
||
response = '<span class="error">只读文件系统: ' + cmd + ' 命令已被禁用</span>';
|
||
break;
|
||
default:
|
||
if (command.trim() !== '') {
|
||
response = '<span class="error">命令未找到: ' + cmd + '</span>';
|
||
} else {
|
||
return;
|
||
}
|
||
}
|
||
|
||
if (response) {
|
||
const responseDiv = document.createElement('div');
|
||
responseDiv.style.marginTop = '5px';
|
||
responseDiv.innerHTML = response;
|
||
output.appendChild(responseDiv);
|
||
}
|
||
|
||
if (response.length > 50) {
|
||
const lastChild = output.lastChild;
|
||
if (lastChild) {
|
||
lastChild.classList.add('typewriter');
|
||
setTimeout(() => lastChild.classList.remove('typewriter'), 2000);
|
||
}
|
||
}
|
||
}
|
||
|
||
function getCurrentDirectory() {
|
||
let current = state.fileSystem.root;
|
||
for (let dir of state.currentDirectory) {
|
||
if (current.children && current.children[dir]) {
|
||
current = current.children[dir];
|
||
} else {
|
||
return state.fileSystem.root;
|
||
}
|
||
}
|
||
return current;
|
||
}
|
||
|
||
function openFileManager() {
|
||
if (state.apps['file-manager']) {
|
||
activateWindow('file-manager');
|
||
return;
|
||
}
|
||
|
||
const content = `
|
||
<div class="file-manager">
|
||
<div class="fm-sidebar">
|
||
<div style="color: var(--neon-cyan); margin-bottom: 10px; font-family: 'Orbitron', sans-serif;">位置</div>
|
||
<div style="cursor: pointer; margin-bottom: 8px;" onclick="resetFMPath()">🏠 根目录</div>
|
||
<div style="cursor: pointer; margin-bottom: 8px;" onclick="setFMPath(['Documents'])">📁 Documents</div>
|
||
<div style="cursor: pointer; margin-bottom: 8px;" onclick="setFMPath(['Projects'])">📁 Projects</div>
|
||
<div style="cursor: pointer; margin-bottom: 8px;" onclick="setFMPath(['Music'])">📁 Music</div>
|
||
<div style="margin-top: 20px; padding-top: 10px; border-top: 1px solid rgba(5, 217, 232, 0.2);">
|
||
<div style="font-size: 0.7rem; color: var(--neon-purple);">
|
||
当前: /${state.currentDirectory.join('/')}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="fm-main" id="fm-main"></div>
|
||
</div>
|
||
`;
|
||
|
||
createWindow('file-manager', '文件管理器', 'fas fa-folder', content);
|
||
|
||
setTimeout(() => renderFileManager(), 100);
|
||
}
|
||
|
||
function renderFileManager() {
|
||
const fmMain = document.getElementById('fm-main');
|
||
if (!fmMain) return;
|
||
|
||
const current = getCurrentDirectory();
|
||
let html = '';
|
||
|
||
if (state.currentDirectory.length > 0) {
|
||
html += `
|
||
<div class="fm-item folder" onclick="goUpDirectory()">
|
||
<i class="fas fa-level-up-alt"></i>
|
||
<span>上一级</span>
|
||
</div>
|
||
`;
|
||
}
|
||
|
||
if (current.children) {
|
||
Object.entries(current.children).forEach(([name, item]) => {
|
||
const iconClass = item.type === 'folder' ? 'fas fa-folder' : 'fas fa-file-alt';
|
||
const itemClass = item.type === 'folder' ? 'folder' : 'file';
|
||
html += `
|
||
<div class="fm-item ${itemClass}" oncontextmenu="showFMContextMenu(event, '${name}', '${item.type}')" onclick="openFMItem('${name}', '${item.type}')">
|
||
<i class="${iconClass}"></i>
|
||
<span>${name}</span>
|
||
</div>
|
||
`;
|
||
});
|
||
}
|
||
fmMain.innerHTML = html;
|
||
}
|
||
|
||
function setFMPath(path) {
|
||
state.currentDirectory = path;
|
||
setTimeout(() => renderFileManager(), 50);
|
||
}
|
||
|
||
function resetFMPath() {
|
||
state.currentDirectory = [];
|
||
setTimeout(() => renderFileManager(), 50);
|
||
}
|
||
|
||
function goUpDirectory() {
|
||
if (state.currentDirectory.length > 0) {
|
||
state.currentDirectory.pop();
|
||
setTimeout(() => renderFileManager(), 50);
|
||
}
|
||
}
|
||
|
||
function openFMItem(name, type) {
|
||
if (type === 'folder') {
|
||
state.currentDirectory.push(name);
|
||
setTimeout(() => renderFileManager(), 50);
|
||
} else {
|
||
const current = getCurrentDirectory();
|
||
if (current.children[name]) {
|
||
showNotification('info', '文件预览', '文件: ' + name + ' \\n内容已显示在终端(使用 cat 命令)');
|
||
}
|
||
}
|
||
}
|
||
|
||
function showFMContextMenu(event, name, type) {
|
||
event.preventDefault();
|
||
event.stopPropagation();
|
||
|
||
const contextMenu = document.getElementById('context-menu');
|
||
contextMenu.innerHTML = `
|
||
<div class="context-menu-item" onclick="showNotification('info', '属性', '文件: ${name} \\n类型: ${type} \\n大小: ' + (Math.floor(Math.random() * 1000)) + 'KB')">
|
||
<i class="fas fa-info-circle"></i> 属性
|
||
</div>
|
||
<div class="context-menu-item" onclick="showNotification('warning', '权限', '该操作需要管理员权限')">
|
||
<i class="fas fa-lock"></i> 权限管理
|
||
</div>
|
||
${type === 'file' ? `
|
||
<div class="context-menu-item" onclick="showNotification('info', '编辑', '在终端使用 cat 查看内容')">
|
||
<i class="fas fa-edit"></i> 编辑
|
||
</div>
|
||
` : ''}
|
||
<div class="context-menu-divider"></div>
|
||
<div class="context-menu-item" onclick="showNotification('error', '错误', '只读文件系统:无法删除')">
|
||
<i class="fas fa-trash"></i> 删除
|
||
</div>
|
||
`;
|
||
|
||
contextMenu.style.display = 'block';
|
||
contextMenu.style.left = event.pageX + 'px';
|
||
contextMenu.style.top = event.pageY + 'px';
|
||
|
||
setTimeout(() => {
|
||
document.addEventListener('click', closeContextMenuOnce);
|
||
}, 100);
|
||
}
|
||
|
||
function openBrowser() {
|
||
if (state.apps['browser']) {
|
||
activateWindow('browser');
|
||
return;
|
||
}
|
||
|
||
const content = `
|
||
<div class="browser">
|
||
<div class="browser-toolbar">
|
||
<input type="text" class="browser-url" id="browser-url" value="https://example.com" placeholder="输入URL...">
|
||
<button class="browser-btn" onclick="navigateBrowser()">前往</button>
|
||
<button class="browser-btn" onclick="refreshBrowser()">刷新</button>
|
||
</div>
|
||
<div class="browser-content" id="browser-content">
|
||
<iframe src="https://example.com"></iframe>
|
||
</div>
|
||
</div>
|
||
`;
|
||
|
||
createWindow('browser', 'Web浏览器', 'fas fa-globe', content);
|
||
}
|
||
|
||
function navigateBrowser() {
|
||
const urlInput = document.getElementById('browser-url');
|
||
const content = document.getElementById('browser-content');
|
||
if (urlInput && content) {
|
||
let url = urlInput.value;
|
||
if (!url.startsWith('http://') && !url.startsWith('https://')) {
|
||
url = 'https://' + url;
|
||
}
|
||
content.innerHTML = '<iframe src="' + url + '"></iframe>';
|
||
showNotification('info', '浏览器', '正在访问: ' + url);
|
||
}
|
||
}
|
||
|
||
function refreshBrowser() {
|
||
const content = document.getElementById('browser-content');
|
||
if (content) {
|
||
const iframe = content.querySelector('iframe');
|
||
if (iframe) {
|
||
iframe.src = iframe.src;
|
||
showNotification('info', '浏览器', '页面已刷新');
|
||
}
|
||
}
|
||
}
|
||
|
||
function openSettings() {
|
||
if (state.apps['settings']) {
|
||
activateWindow('settings');
|
||
return;
|
||
}
|
||
|
||
const content = `
|
||
<div class="settings">
|
||
<div class="setting-group">
|
||
<h3>主题设置</h3>
|
||
<div class="setting-item">
|
||
<span class="setting-label">当前主题: ${state.settings.theme}</span>
|
||
<div class="setting-control">
|
||
<button onclick="changeTheme()">切换主题</button>
|
||
</div>
|
||
</div>
|
||
<div class="setting-item">
|
||
<span class="setting-label">壁纸风格</span>
|
||
<div class="setting-control">
|
||
<button onclick="changeWallpaper()">更换壁纸</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="setting-group">
|
||
<h3>系统设置</h3>
|
||
<div class="setting-item">
|
||
<span class="setting-label">音量: ${Math.round(state.settings.volume * 100)}%</span>
|
||
<div class="setting-control">
|
||
<input type="range" min="0" max="100" value="${state.settings.volume * 100}"
|
||
oninput="setVolume(this.value)">
|
||
</div>
|
||
</div>
|
||
<div class="setting-item">
|
||
<span class="setting-label">启用通知</span>
|
||
<div class="setting-control">
|
||
<button onclick="toggleNotifications()">${state.settings.notifications ? '禁用' : '启用'}</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="setting-group">
|
||
<h3>隐私与安全</h3>
|
||
<div class="setting-item">
|
||
<span class="setting-label">清除本地数据</span>
|
||
<div class="setting-control">
|
||
<button onclick="clearData()">清除</button>
|
||
</div>
|
||
</div>
|
||
<div class="setting-item">
|
||
<span class="setting-label">导出配置</span>
|
||
<div class="setting-control">
|
||
<button onclick="exportConfig()">导出</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
`;
|
||
|
||
createWindow('settings', '设置中心', 'fas fa-cog', content);
|
||
}
|
||
|
||
function changeTheme() {
|
||
const themes = ['cyberpunk', 'retro', 'minimal', 'dark', 'light'];
|
||
const currentIndex = themes.indexOf(state.settings.theme);
|
||
const nextIndex = (currentIndex + 1) % themes.length;
|
||
state.settings.theme = themes[nextIndex];
|
||
saveSettings();
|
||
applyTheme();
|
||
showNotification('success', '主题切换', '已切换至: ' + themes[nextIndex]);
|
||
|
||
setTimeout(() => {
|
||
if (state.apps['settings']) {
|
||
closeWindow('settings');
|
||
openSettings();
|
||
}
|
||
}, 500);
|
||
}
|
||
|
||
function changeWallpaper() {
|
||
const wallpapers = ['default', 'neon', 'grid', 'city', 'matrix'];
|
||
const currentWallpaper = state.settings.wallpaper;
|
||
const nextIndex = (wallpapers.indexOf(currentWallpaper) + 1) % wallpapers.length;
|
||
state.settings.wallpaper = wallpapers[nextIndex];
|
||
saveSettings();
|
||
applyWallpaper();
|
||
showNotification('success', '壁纸更换', '已更换为: ' + wallpapers[nextIndex]);
|
||
}
|
||
|
||
function setVolume(value) {
|
||
state.settings.volume = value / 100;
|
||
saveSettings();
|
||
if (state.apps['settings']) {
|
||
const label = document.querySelector('.setting-item span');
|
||
if (label) {
|
||
label.textContent = '音量: ' + value + '%';
|
||
}
|
||
}
|
||
}
|
||
|
||
function toggleNotifications() {
|
||
state.settings.notifications = !state.settings.notifications;
|
||
saveSettings();
|
||
showNotification('info', '通知设置', '通知已' + (state.settings.notifications ? '启用' : '禁用'));
|
||
|
||
setTimeout(() => {
|
||
if (state.apps['settings']) {
|
||
closeWindow('settings');
|
||
openSettings();
|
||
}
|
||
}, 500);
|
||
}
|
||
|
||
function clearData() {
|
||
if (confirm('确定要清除所有本地数据吗?这将重置所有设置。')) {
|
||
localStorage.removeItem('neon-os-settings');
|
||
showNotification('success', '数据清除', '本地数据已清除');
|
||
setTimeout(rebootSystem, 1000);
|
||
}
|
||
}
|
||
|
||
function exportConfig() {
|
||
const config = JSON.stringify(state.settings, null, 2);
|
||
showNotification('info', '导出配置', '配置信息已复制到终端(模拟操作)\\n\\n' + config);
|
||
}
|
||
|
||
function openMusicPlayer() {
|
||
if (state.apps['music-player']) {
|
||
activateWindow('music-player');
|
||
return;
|
||
}
|
||
|
||
const content = `
|
||
<div class="music-player">
|
||
<div class="album-cover">
|
||
<i class="fas fa-music"></i>
|
||
</div>
|
||
<div class="music-info">
|
||
<div class="music-title" id="music-title">${state.musicPlayer.tracks[state.musicPlayer.currentTrack].title}</div>
|
||
<div class="music-artist" id="music-artist">${state.musicPlayer.tracks[state.musicPlayer.currentTrack].artist}</div>
|
||
<div class="progress-bar" onclick="seekMusic(event)">
|
||
<div class="progress-fill" id="music-progress"></div>
|
||
</div>
|
||
<div style="display: flex; justify-content: space-between; margin-top: 5px; font-size: 0.7rem; color: var(--neon-purple);">
|
||
<span id="current-time">0:00</span>
|
||
<span id="total-time">${formatTime(state.musicPlayer.tracks[state.musicPlayer.currentTrack].duration)}</span>
|
||
</div>
|
||
<div class="audio-visualizer" id="audio-visualizer"></div>
|
||
</div>
|
||
<div class="music-controls">
|
||
<div class="music-control" onclick="prevTrack()"><i class="fas fa-step-backward"></i></div>
|
||
<div class="music-control" id="play-pause-btn" onclick="togglePlay()"><i class="fas fa-play"></i></div>
|
||
<div class="music-control" onclick="nextTrack()"><i class="fas fa-step-forward"></i></div>
|
||
</div>
|
||
<div class="volume-control">
|
||
<i class="fas fa-volume-up"></i>
|
||
<input type="range" min="0" max="100" value="${state.settings.volume * 100}" oninput="setTrackVolume(this.value)">
|
||
</div>
|
||
</div>
|
||
`;
|
||
|
||
createWindow('music-player', '音乐播放器', 'fas fa-music', content);
|
||
|
||
setTimeout(() => {
|
||
if (!state.musicPlayer.playing) {
|
||
createAudioVisualizer();
|
||
}
|
||
}, 100);
|
||
}
|
||
|
||
function togglePlay() {
|
||
state.musicPlayer.playing = !state.musicPlayer.playing;
|
||
const btn = document.getElementById('play-pause-btn');
|
||
|
||
if (btn) {
|
||
btn.innerHTML = state.musicPlayer.playing ? '<i class="fas fa-pause"></i>' : '<i class="fas fa-play"></i>';
|
||
}
|
||
|
||
if (state.musicPlayer.playing) {
|
||
showNotification('info', '音乐播放器', '正在播放: ' + state.musicPlayer.tracks[state.musicPlayer.currentTrack].title);
|
||
startMusicProgress();
|
||
} else {
|
||
showNotification('info', '音乐播放器', '已暂停');
|
||
stopMusicProgress();
|
||
}
|
||
}
|
||
|
||
function prevTrack() {
|
||
const currentIndex = state.musicPlayer.currentTrack;
|
||
state.musicPlayer.currentTrack = currentIndex > 0 ? currentIndex - 1 : state.musicPlayer.tracks.length - 1;
|
||
updateTrackInfo();
|
||
showNotification('info', '音乐切换', '播放: ' + state.musicPlayer.tracks[state.musicPlayer.currentTrack].title);
|
||
}
|
||
|
||
function nextTrack() {
|
||
const currentIndex = state.musicPlayer.currentTrack;
|
||
state.musicPlayer.currentTrack = (currentIndex + 1) % state.musicPlayer.tracks.length;
|
||
updateTrackInfo();
|
||
showNotification('info', '音乐切换', '播放: ' + state.musicPlayer.tracks[state.musicPlayer.currentTrack].title);
|
||
}
|
||
|
||
function updateTrackInfo() {
|
||
const track = state.musicPlayer.tracks[state.musicPlayer.currentTrack];
|
||
const titleEl = document.getElementById('music-title');
|
||
const artistEl = document.getElementById('music-artist');
|
||
const totalTimeEl = document.getElementById('total-time');
|
||
|
||
if (titleEl) titleEl.textContent = track.title;
|
||
if (artistEl) artistEl.textContent = track.artist;
|
||
if (totalTimeEl) totalTimeEl.textContent = formatTime(track.duration);
|
||
|
||
const progress = document.getElementById('music-progress');
|
||
if (progress) progress.style.width = '0%';
|
||
|
||
if (state.musicPlayer.playing) {
|
||
stopMusicProgress();
|
||
setTimeout(startMusicProgress, 100);
|
||
}
|
||
}
|
||
|
||
function startMusicProgress() {
|
||
stopMusicProgress();
|
||
const track = state.musicPlayer.tracks[state.musicPlayer.currentTrack];
|
||
const progress = document.getElementById('music-progress');
|
||
const currentTimeEl = document.getElementById('current-time');
|
||
|
||
if (!progress || !currentTimeEl) return;
|
||
|
||
let currentSeconds = 0;
|
||
|
||
state.musicPlayer.progressInterval = setInterval(() => {
|
||
currentSeconds++;
|
||
if (currentSeconds >= track.duration) {
|
||
nextTrack();
|
||
return;
|
||
}
|
||
|
||
const percentage = (currentSeconds / track.duration) * 100;
|
||
progress.style.width = percentage + '%';
|
||
currentTimeEl.textContent = formatTime(currentSeconds);
|
||
|
||
updateVisualizer();
|
||
}, 1000);
|
||
}
|
||
|
||
function stopMusicProgress() {
|
||
if (state.musicPlayer.progressInterval) {
|
||
clearInterval(state.musicPlayer.progressInterval);
|
||
state.musicPlayer.progressInterval = null;
|
||
}
|
||
}
|
||
|
||
function seekMusic(event) {
|
||
if (state.musicPlayer.playing) {
|
||
const bar = event.currentTarget;
|
||
const rect = bar.getBoundingClientRect();
|
||
const clickX = event.clientX - rect.left;
|
||
const percentage = clickX / rect.width;
|
||
const track = state.musicPlayer.tracks[state.musicPlayer.currentTrack];
|
||
const newSeconds = Math.floor(percentage * track.duration);
|
||
|
||
const progress = document.getElementById('music-progress');
|
||
const currentTimeEl = document.getElementById('current-time');
|
||
|
||
if (progress && currentTimeEl) {
|
||
progress.style.width = (percentage * 100) + '%';
|
||
currentTimeEl.textContent = formatTime(newSeconds);
|
||
}
|
||
}
|
||
}
|
||
|
||
function setTrackVolume(value) {
|
||
state.settings.volume = value / 100;
|
||
saveSettings();
|
||
showNotification('info', '音量调整', '当前音量: ' + value + '%');
|
||
}
|
||
|
||
function createAudioVisualizer() {
|
||
const visualizer = document.getElementById('audio-visualizer');
|
||
if (!visualizer) return;
|
||
|
||
visualizer.innerHTML = '';
|
||
for (let i = 0; i < 20; i++) {
|
||
const bar = document.createElement('div');
|
||
bar.className = 'audio-bar';
|
||
bar.style.height = Math.random() * 20 + 5 + 'px';
|
||
visualizer.appendChild(bar);
|
||
}
|
||
}
|
||
|
||
function updateVisualizer() {
|
||
const visualizer = document.getElementById('audio-visualizer');
|
||
if (!visualizer) return;
|
||
|
||
if (state.musicPlayer.playing) {
|
||
const bars = visualizer.children;
|
||
for (let bar of bars) {
|
||
bar.style.height = Math.random() * 30 + 10 + 'px';
|
||
}
|
||
}
|
||
}
|
||
|
||
function formatTime(seconds) {
|
||
const mins = Math.floor(seconds / 60);
|
||
const secs = seconds % 60;
|
||
return mins + ':' + (secs < 10 ? '0' : '') + secs;
|
||
}
|
||
|
||
function openNotepad() {
|
||
if (state.apps['notepad']) {
|
||
activateWindow('notepad');
|
||
return;
|
||
}
|
||
|
||
const savedContent = localStorage.getItem('neon-os-notepad') || '';
|
||
|
||
const content = `
|
||
<div class="notepad">
|
||
<div class="notepad-toolbar">
|
||
<button class="notepad-btn" onclick="saveNotepad()">保存</button>
|
||
<button class="notepad-btn" onclick="clearNotepad()">清空</button>
|
||
<button class="notepad-btn" onclick="exportNotepad()">导出</button>
|
||
</div>
|
||
<textarea class="notepad-editor" id="notepad-editor" placeholder="输入您的笔记...">${savedContent}</textarea>
|
||
<div class="notepad-status" id="notepad-status">已保存至本地存储</div>
|
||
</div>
|
||
`;
|
||
|
||
createWindow('notepad', '便签', 'fas fa-sticky-note', content);
|
||
|
||
setTimeout(() => {
|
||
const editor = document.getElementById('notepad-editor');
|
||
if (editor) {
|
||
editor.addEventListener('input', () => {
|
||
localStorage.setItem('neon-os-notepad', editor.value);
|
||
updateNotepadStatus('已自动保存');
|
||
});
|
||
}
|
||
}, 100);
|
||
}
|
||
|
||
function saveNotepad() {
|
||
const editor = document.getElementById('notepad-editor');
|
||
if (editor) {
|
||
localStorage.setItem('neon-os-notepad', editor.value);
|
||
updateNotepadStatus('保存成功!');
|
||
showNotification('success', '便签', '笔记已保存');
|
||
}
|
||
}
|
||
|
||
function clearNotepad() {
|
||
const editor = document.getElementById('notepad-editor');
|
||
if (editor && confirm('确定要清空所有内容吗?')) {
|
||
editor.value = '';
|
||
localStorage.removeItem('neon-os-notepad');
|
||
updateNotepadStatus('已清空');
|
||
showNotification('success', '便签', '内容已清空');
|
||
}
|
||
}
|
||
|
||
function exportNotepad() {
|
||
const editor = document.getElementById('notepad-editor');
|
||
if (editor) {
|
||
const content = editor.value;
|
||
showNotification('info', '导出', '笔记内容已复制到剪贴板(模拟操作)');
|
||
navigator.clipboard.writeText(content).catch(() => {});
|
||
}
|
||
}
|
||
|
||
function updateNotepadStatus(message) {
|
||
const status = document.getElementById('notepad-status');
|
||
if (status) {
|
||
status.textContent = message;
|
||
setTimeout(() => {
|
||
status.textContent = '已保存至本地存储';
|
||
}, 2000);
|
||
}
|
||
}
|
||
|
||
function openMonitor() {
|
||
if (state.apps['monitor']) {
|
||
activateWindow('monitor');
|
||
return;
|
||
}
|
||
|
||
const content = `
|
||
<div class="monitor" id="monitor-content">
|
||
<div class="monitor-item">
|
||
<div class="monitor-item-title">CPU 使用率</div>
|
||
<div class="monitor-chart" id="cpu-chart"></div>
|
||
<div class="monitor-stats" id="cpu-stats">核心: 4 | 频率: 3.2GHz | 负载: 42%</div>
|
||
</div>
|
||
<div class="monitor-item">
|
||
<div class="monitor-item-title">内存使用</div>
|
||
<div class="monitor-chart" id="mem-chart"></div>
|
||
<div class="monitor-stats" id="mem-stats">总共: 16GB | 已用: 9.8GB | 可用: 6.2GB</div>
|
||
</div>
|
||
<div class="monitor-item">
|
||
<div class="monitor-item-title">磁盘 I/O</div>
|
||
<div class="monitor-chart" id="disk-chart"></div>
|
||
<div class="monitor-stats" id="disk-stats">读取: 12MB/s | 写入: 8MB/s</div>
|
||
</div>
|
||
<div class="monitor-item">
|
||
<div class="monitor-item-title">网络状态</div>
|
||
<div class="monitor-chart" id="network-chart"></div>
|
||
<div class="monitor-stats" id="network-stats">下载: 45Mbps | 上传: 12Mbps</div>
|
||
</div>
|
||
</div>
|
||
`;
|
||
|
||
createWindow('monitor', '系统监控', 'fas fa-chart-line', content);
|
||
|
||
setTimeout(() => startMonitorUpdate(), 500);
|
||
}
|
||
|
||
function startMonitorUpdate() {
|
||
stopMonitorCharts();
|
||
|
||
if (!state.apps['monitor']) return;
|
||
|
||
state.monitorInterval = setInterval(() => {
|
||
if (!state.apps['monitor']) {
|
||
stopMonitorCharts();
|
||
return;
|
||
}
|
||
|
||
updateMonitorChart('cpu-chart', Math.floor(Math.random() * 40) + 30, 'cpu-stats',
|
||
'核心: 4 | 频率: 3.2GHz | 负载: ' + (Math.floor(Math.random() * 20) + 30) + '%');
|
||
|
||
updateMonitorChart('mem-chart', Math.floor(Math.random() * 30) + 40, 'mem-stats',
|
||
'总共: 16GB | 已用: ' + (Math.random() * 4 + 9).toFixed(1) + 'GB | 可用: ' + (Math.random() * 2 + 4).toFixed(1) + 'GB');
|
||
|
||
updateMonitorChart('disk-chart', Math.floor(Math.random() * 30) + 20, 'disk-stats',
|
||
'读取: ' + (Math.floor(Math.random() * 20) + 5) + 'MB/s | 写入: ' + (Math.floor(Math.random() * 15) + 3) + 'MB/s');
|
||
|
||
updateMonitorChart('network-chart', Math.floor(Math.random() * 30) + 20, 'network-stats',
|
||
'下载: ' + (Math.floor(Math.random() * 50) + 10) + 'Mbps | 上传: ' + (Math.floor(Math.random() * 20) + 5) + 'Mbps');
|
||
}, 2000);
|
||
}
|
||
|
||
function updateMonitorChart(chartId, value, statsId, statsText) {
|
||
const chart = document.getElementById(chartId);
|
||
const stats = document.getElementById(statsId);
|
||
|
||
if (chart && stats) {
|
||
chart.innerHTML = '';
|
||
const barContainer = document.createElement('div');
|
||
barContainer.className = 'monitor-bar-chart';
|
||
|
||
for (let i = 0; i < 8; i++) {
|
||
const barItem = document.createElement('div');
|
||
barItem.className = 'monitor-bar-item';
|
||
const randomValue = Math.random() * 30 + value - 15;
|
||
barItem.style.height = Math.max(5, randomValue) + '%';
|
||
barContainer.appendChild(barItem);
|
||
}
|
||
|
||
chart.appendChild(barContainer);
|
||
|
||
if (stats) {
|
||
stats.textContent = statsText;
|
||
}
|
||
}
|
||
}
|
||
|
||
function stopMonitorCharts() {
|
||
if (state.monitorInterval) {
|
||
clearInterval(state.monitorInterval);
|
||
state.monitorInterval = null;
|
||
}
|
||
}
|
||
|
||
function openAbout() {
|
||
if (state.apps['about']) {
|
||
activateWindow('about');
|
||
return;
|
||
}
|
||
|
||
const content = `
|
||
<div style="padding: 20px; line-height: 1.6; color: var(--neon-blue);">
|
||
<div style="text-align: center; margin-bottom: 20px;">
|
||
<h2 style="color: var(--neon-pink); font-family: 'Orbitron', sans-serif; margin-bottom: 10px;">NEON-OS</h2>
|
||
<p style="color: var(--neon-cyan);">赛博朋克未来操作系统</p>
|
||
</div>
|
||
|
||
<div style="background: rgba(0,0,0,0.3); padding: 15px; border-radius: 8px; margin-bottom: 15px;">
|
||
<h3 style="color: var(--neon-pink); margin-bottom: 8px;">系统规格</h3>
|
||
<p>版本: <span class="highlight">1.0.0</span></p>
|
||
<p>架构: WebAssembly/JS</p>
|
||
<p>构建日期: 2024</p>
|
||
</div>
|
||
|
||
<div style="background: rgba(0,0,0,0.3); padding: 15px; border-radius: 8px; margin-bottom: 15px;">
|
||
<h3 style="color: var(--neon-pink); margin-bottom: 8px;">功能特性</h3>
|
||
<ul style="margin-left: 20px;">
|
||
<li>完整的窗口管理系统</li>
|
||
<li>终端模拟器(支持Linux命令)</li>
|
||
<li>多媒体音乐播放器</li>
|
||
<li>系统监控与性能分析</li>
|
||
<li>本地化数据持久化</li>
|
||
<li>赛博朋克主题UI</li>
|
||
</ul>
|
||
</div>
|
||
|
||
<div style="text-align: center; margin-top: 20px; padding-top: 20px; border-top: 1px solid rgba(5, 217, 232, 0.2);">
|
||
<p style="color: var(--neon-purple);">© 2024 NEON-OS Project | 全栈工程示例</p>
|
||
<p style="color: var(--neon-cyan); font-size: 0.8rem; margin-top: 8px;">右键桌面探索更多功能</p>
|
||
</div>
|
||
</div>
|
||
`;
|
||
|
||
createWindow('about', '关于系统', 'fas fa-info-circle', content);
|
||
}
|
||
|
||
// 系统函数
|
||
function toggleStartMenu() {
|
||
const menu = document.getElementById('start-menu');
|
||
if (menu.style.display === 'block') {
|
||
menu.style.display = 'none';
|
||
} else {
|
||
menu.style.display = 'block';
|
||
setTimeout(() => {
|
||
document.addEventListener('click', closeStartMenuOnce);
|
||
}, 100);
|
||
}
|
||
}
|
||
|
||
function closeStartMenuOnce(e) {
|
||
const menu = document.getElementById('start-menu');
|
||
const startBtn = document.querySelector('.taskbar-start');
|
||
|
||
if (menu && menu.style.display === 'block' &&
|
||
!menu.contains(e.target) && !startBtn.contains(e.target)) {
|
||
menu.style.display = 'none';
|
||
document.removeEventListener('click', closeStartMenuOnce);
|
||
}
|
||
}
|
||
|
||
function toggleVolume() {
|
||
showNotification('info', '音量', '当前音量: ' + Math.round(state.settings.volume * 100) + '%');
|
||
}
|
||
|
||
function showNotification(type, title, message) {
|
||
if (!state.settings.notifications) return;
|
||
|
||
const area = document.getElementById('notification-area');
|
||
const notification = document.createElement('div');
|
||
notification.className = 'notification ' + type;
|
||
|
||
const icons = {
|
||
success: 'fa-check-circle',
|
||
error: 'fa-times-circle',
|
||
warning: 'fa-exclamation-triangle',
|
||
info: 'fa-info-circle'
|
||
};
|
||
|
||
notification.innerHTML = `
|
||
<div class="notification-header">
|
||
<div class="notification-title"><i class="fas ${icons[type]}"></i> ${title}</div>
|
||
<div class="notification-close" onclick="this.parentElement.parentElement.remove()">
|
||
<i class="fas fa-times"></i>
|
||
</div>
|
||
</div>
|
||
<div class="notification-body">${message}</div>
|
||
`;
|
||
|
||
area.appendChild(notification);
|
||
|
||
setTimeout(() => {
|
||
if (notification.parentElement) {
|
||
notification.style.opacity = '0';
|
||
notification.style.transform = 'translateX(100%)';
|
||
setTimeout(() => notification.remove(), 300);
|
||
}
|
||
}, 4000);
|
||
}
|
||
|
||
function closeContextMenuOnce(e) {
|
||
const contextMenu = document.getElementById('context-menu');
|
||
if (contextMenu && contextMenu.style.display === 'block' && !contextMenu.contains(e.target)) {
|
||
contextMenu.style.display = 'none';
|
||
document.removeEventListener('click', closeContextMenuOnce);
|
||
}
|
||
}
|
||
|
||
// 桌面右键菜单
|
||
document.addEventListener('contextmenu', (e) => {
|
||
const desktop = document.getElementById('desktop');
|
||
const contextMenu = document.getElementById('context-menu');
|
||
|
||
// 确保是在桌面上的右键
|
||
if (!desktop || desktop.style.display === 'none') return;
|
||
if (desktop.contains(e.target)) {
|
||
e.preventDefault();
|
||
contextMenu.style.display = 'block';
|
||
contextMenu.style.left = e.pageX + 'px';
|
||
contextMenu.style.top = e.pageY + 'px';
|
||
|
||
setTimeout(() => {
|
||
document.addEventListener('click', closeContextMenuOnce);
|
||
}, 100);
|
||
}
|
||
});
|
||
|
||
function refreshDesktop() {
|
||
if (state.apps['file-manager']) {
|
||
renderFileManager();
|
||
}
|
||
showNotification('success', '刷新', '桌面已刷新');
|
||
}
|
||
|
||
// 主题和壁纸应用
|
||
function applyTheme() {
|
||
const root = document.documentElement;
|
||
const theme = state.settings.theme;
|
||
|
||
const themes = {
|
||
cyberpunk: {
|
||
neonPink: '#ff2a6d',
|
||
neonBlue: '#05d9e8',
|
||
neonPurple: '#d100d1',
|
||
neonCyan: '#00ff9f',
|
||
darkBg: '#0d0d16'
|
||
},
|
||
retro: {
|
||
neonPink: '#ff7700',
|
||
neonBlue: '#00ff88',
|
||
neonPurple: '#ff00aa',
|
||
neonCyan: '#ffff00',
|
||
darkBg: '#1a1a2e'
|
||
},
|
||
minimal: {
|
||
neonPink: '#00ff88',
|
||
neonBlue: '#00ccff',
|
||
neonPurple: '#aa88ff',
|
||
neonCyan: '#ffffff',
|
||
darkBg: '#0a0a0a'
|
||
},
|
||
dark: {
|
||
neonPink: '#bb0044',
|
||
neonBlue: '#0088cc',
|
||
neonPurple: '#6600cc',
|
||
neonCyan: '#00cc88',
|
||
darkBg: '#000000'
|
||
},
|
||
light: {
|
||
neonPink: '#cc0066',
|
||
neonBlue: '#0066cc',
|
||
neonPurple: '#6600cc',
|
||
neonCyan: '#009966',
|
||
darkBg: '#f0f0f0'
|
||
}
|
||
};
|
||
|
||
const selectedTheme = themes[theme] || themes.cyberpunk;
|
||
|
||
root.style.setProperty('--neon-pink', selectedTheme.neonPink);
|
||
root.style.setProperty('--neon-blue', selectedTheme.neonBlue);
|
||
root.style.setProperty('--neon-purple', selectedTheme.neonPurple);
|
||
root.style.setProperty('--neon-cyan', selectedTheme.neonCyan);
|
||
root.style.setProperty('--dark-bg', selectedTheme.darkBg);
|
||
|
||
if (theme === 'light') {
|
||
root.style.setProperty('--glass-bg', 'rgba(255, 255, 255, 0.8)');
|
||
root.style.setProperty('--glass-border', 'rgba(0, 102, 204, 0.3)');
|
||
} else {
|
||
root.style.setProperty('--glass-bg', 'rgba(13, 13, 22, 0.7)');
|
||
root.style.setProperty('--glass-border', 'rgba(5, 217, 232, 0.3)');
|
||
}
|
||
}
|
||
|
||
function applyWallpaper() {
|
||
const bg = document.querySelector('.desktop-bg');
|
||
const wallpaper = state.settings.wallpaper;
|
||
|
||
if (!bg) return;
|
||
|
||
let background = '';
|
||
|
||
switch(wallpaper) {
|
||
case 'neon':
|
||
background = `linear-gradient(135deg, rgba(255, 42, 109, 0.1), rgba(5, 217, 232, 0.1)), radial-gradient(circle at 20% 50%, rgba(255, 42, 109, 0.1), transparent 50%), radial-gradient(circle at 80% 80%, rgba(5, 217, 232, 0.1), transparent 50%)`;
|
||
break;
|
||
case 'grid':
|
||
background = `linear-gradient(rgba(0, 255, 159, 0.05) 1px, transparent 1px), linear-gradient(90deg, rgba(0, 255, 159, 0.05) 1px, transparent 1px), repeating-linear-gradient(0deg, transparent, transparent 2px, rgba(0, 255, 159, 0.03) 2px, rgba(0, 255, 159, 0.03) 3px), repeating-linear-gradient(90deg, transparent, transparent 2px, rgba(0, 255, 159, 0.03) 2px, rgba(0, 255, 159, 0.03) 3px)`;
|
||
break;
|
||
case 'city':
|
||
background = `linear-gradient(180deg, rgba(13, 13, 22, 0.7), rgba(13, 13, 22, 0.3)), repeating-linear-gradient(0deg, transparent, transparent 2px, rgba(255, 42, 109, 0.1) 2px, rgba(255, 42, 109, 0.1) 3px)`;
|
||
break;
|
||
case 'matrix':
|
||
background = `linear-gradient(rgba(0, 255, 159, 0.02) 2px, transparent 2px), linear-gradient(90deg, rgba(0, 255, 159, 0.02) 2px, transparent 2px)`;
|
||
break;
|
||
default:
|
||
background = `linear-gradient(rgba(13, 13, 22, 0.9), rgba(13, 13, 22, 0.7)), repeating-linear-gradient(0deg, transparent, transparent 2px, var(--grid-color) 2px, var(--grid-color) 3px), repeating-linear-gradient(90deg, transparent, transparent 2px, var(--grid-color) 2px, var(--grid-color) 3px)`;
|
||
}
|
||
|
||
bg.style.background = background;
|
||
}
|
||
|
||
function saveSettings() {
|
||
localStorage.setItem('neon-os-settings', JSON.stringify(state.settings));
|
||
}
|
||
|
||
// 矩阵雨特效
|
||
function startMatrixRain() {
|
||
const canvas = document.getElementById('matrix-canvas');
|
||
const ctx = canvas.getContext('2d');
|
||
|
||
canvas.style.display = 'block';
|
||
state.matrixRunning = true;
|
||
|
||
canvas.width = window.innerWidth;
|
||
canvas.height = window.innerHeight;
|
||
|
||
const cols = Math.floor(canvas.width / 20);
|
||
const drops = [];
|
||
const chars = '01abcdef0123456789@$%&*';
|
||
|
||
for (let i = 0; i < cols; i++) {
|
||
drops[i] = 1;
|
||
}
|
||
|
||
function draw() {
|
||
if (!state.matrixRunning) {
|
||
canvas.style.display = 'none';
|
||
return;
|
||
}
|
||
|
||
ctx.fillStyle = 'rgba(0, 0, 0, 0.05)';
|
||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||
|
||
ctx.fillStyle = '#00ff9f';
|
||
ctx.font = '16px monospace';
|
||
|
||
for (let i = 0; i < drops.length; i++) {
|
||
const text = chars.charAt(Math.floor(Math.random() * chars.length));
|
||
ctx.fillText(text, i * 20, drops[i] * 20);
|
||
|
||
if (drops[i] * 20 > canvas.height && Math.random() > 0.975) {
|
||
drops[i] = 0;
|
||
}
|
||
|
||
drops[i]++;
|
||
}
|
||
|
||
requestAnimationFrame(draw);
|
||
}
|
||
|
||
draw();
|
||
|
||
const exitHandler = () => {
|
||
state.matrixRunning = false;
|
||
document.removeEventListener('keydown', exitHandler);
|
||
document.removeEventListener('click', exitHandler);
|
||
};
|
||
|
||
setTimeout(() => {
|
||
document.addEventListener('keydown', exitHandler);
|
||
document.addEventListener('click', exitHandler);
|
||
}, 100);
|
||
}
|
||
|
||
// 系统操作
|
||
function rebootSystem() {
|
||
showNotification('warning', '系统重启', '正在重启系统...');
|
||
setTimeout(() => {
|
||
location.reload();
|
||
}, 2000);
|
||
}
|
||
|
||
function logout() {
|
||
showNotification('info', '切换用户', '正在切换用户...');
|
||
|
||
Object.keys(state.apps).forEach(appId => closeWindow(appId));
|
||
|
||
state.currentDirectory = [];
|
||
|
||
setTimeout(() => {
|
||
document.getElementById('desktop').style.display = 'none';
|
||
document.getElementById('start-menu').style.display = 'none';
|
||
showLockScreen();
|
||
}, 1000);
|
||
}
|
||
|
||
function shutdown() {
|
||
showNotification('error', '关机', '系统正在关闭...');
|
||
const desktop = document.getElementById('desktop');
|
||
if (desktop) desktop.style.opacity = '0';
|
||
setTimeout(() => {
|
||
document.body.innerHTML = `
|
||
<div style="display: flex; justify-content: center; align-items: center; height: 100vh; background: #000; color: var(--neon-pink); font-family: 'Orbitron', sans-serif; font-size: 2rem;">
|
||
系统已关机
|
||
</div>
|
||
`;
|
||
}, 2000);
|
||
}
|
||
|
||
// 键盘快捷键
|
||
document.addEventListener('keydown', (e) => {
|
||
if (e.ctrlKey && e.altKey && e.key === 't') {
|
||
e.preventDefault();
|
||
openTerminal();
|
||
}
|
||
|
||
if (e.ctrlKey && e.altKey && e.key === 'w') {
|
||
e.preventDefault();
|
||
let topZIndex = 0;
|
||
let topAppId = null;
|
||
|
||
Object.entries(state.apps).forEach(([appId, app]) => {
|
||
const zIndex = parseInt(app.element.style.zIndex);
|
||
if (zIndex > topZIndex && !app.minimized) {
|
||
topZIndex = zIndex;
|
||
topAppId = appId;
|
||
}
|
||
});
|
||
|
||
if (topAppId) {
|
||
closeWindow(topAppId);
|
||
}
|
||
}
|
||
|
||
if (e.ctrlKey && e.altKey && e.key === 'm') {
|
||
e.preventDefault();
|
||
let topZIndex = 0;
|
||
let topAppId = null;
|
||
|
||
Object.entries(state.apps).forEach(([appId, app]) => {
|
||
const zIndex = parseInt(app.element.style.zIndex);
|
||
if (zIndex > topZIndex && !app.minimized) {
|
||
topZIndex = zIndex;
|
||
topAppId = appId;
|
||
}
|
||
});
|
||
|
||
if (topAppId) {
|
||
minimizeWindow(topAppId);
|
||
}
|
||
}
|
||
|
||
if (e.ctrlKey && e.altKey && e.key === 'e') {
|
||
e.preventDefault();
|
||
openApp('file-manager');
|
||
}
|
||
});
|
||
|
||
// 窗口点击事件(激活窗口)
|
||
document.addEventListener('click', (e) => {
|
||
const windowElement = e.target.closest('.window');
|
||
if (windowElement && !e.target.closest('.window-control')) {
|
||
const appId = windowElement.id.replace('window-', '');
|
||
activateWindow(appId);
|
||
}
|
||
});
|
||
|
||
// 响应式处理
|
||
window.addEventListener('resize', () => {
|
||
Object.values(state.apps).forEach(app => {
|
||
if (!app.maximized && !app.minimized) {
|
||
const rect = app.element.getBoundingClientRect();
|
||
if (rect.left > window.innerWidth || rect.top > window.innerHeight) {
|
||
app.element.style.left = '50px';
|
||
app.element.style.top = '50px';
|
||
}
|
||
}
|
||
});
|
||
|
||
const matrixCanvas = document.getElementById('matrix-canvas');
|
||
if (matrixCanvas && matrixCanvas.style.display !== 'none') {
|
||
matrixCanvas.width = window.innerWidth;
|
||
matrixCanvas.height = window.innerHeight;
|
||
}
|
||
});
|
||
|
||
// 系统初始化
|
||
document.addEventListener('DOMContentLoaded', () => {
|
||
console.log('[INIT] DOM加载完成,开始初始化系统');
|
||
initSystem();
|
||
|
||
setTimeout(() => {
|
||
applyTheme();
|
||
applyWallpaper();
|
||
}, 100);
|
||
});
|
||
</script>
|
||
</body>
|
||
</html>
|