Windows XP 触控版 · 全功能终极增强版(快捷方式图标API)
正在启动...
🖥️ Windows XP 正在关机
点击屏幕任意位置重新启动
关闭计算机
💤
待机 (S)
关闭 (U)
重新启动 (R)

:(

你的系统遇到了一个无法处理的错误,需要重新启动。

*** STOP: 0x0000007B (0xF78D2524, 0xC0000034, 0x00000000, 0x00000000)

*** INACCESSIBLE_BOOT_DEVICE

如果你第一次看到此界面,请重新启动计算机。如果多次出现,请运行磁盘清理或恢复出厂设置。

请输入密码

🪟 开始
🌐
🎵
🧮
💣
🔊 天气 12:00 PM
'); // --- 4. 在弹窗中渲染 --- const finalBlob = new Blob([htmlContent], { type: 'text/html' }); const finalUrl = URL.createObjectURL(finalBlob); const win = createWindow(file.name.replace('.exe', ''), ``, 800, 600); // 保存资源映射供母体使用 win._resourceMap = resourceMap; // 同时保存到全局备份(增强兼容性) window._currentResourceMap = resourceMap; window._globalAudioMap = resourceMap; // 注册到 xpAudio if (window.xpAudio) { window.xpAudio.registerResourceMap(resourceMap); } console.log('[launchExe] 已加载资源:', Object.keys(resourceMap)); const closeBtn = win.div.querySelector('[data-action="close"]'); if (closeBtn) { closeBtn.addEventListener('click', () => { if (win._resourceMap) { for (let key in win._resourceMap) { if (win._resourceMap[key]?.startsWith('blob:')) { URL.revokeObjectURL(win._resourceMap[key]); } } win._resourceMap = null; } // 清理全局备份 window._currentResourceMap = null; window._globalAudioMap = null; URL.revokeObjectURL(finalUrl); }); } } catch (err) { showXPError('启动失败', err.message); } } async function exportUserData() { const exportData = { version:1, user:currentUserId, registry:registry, fileSystem:JSON.parse(JSON.stringify(fileSystem)), shortcuts:desktopShortcuts, wallpaper:desktop.style.backgroundImage.slice(5,-2)||'', dbFiles:[] }; async function collectDBFiles(node) { if(node.type==='file' && node.dbKey) { const blob = await getFileFromDB(node.dbKey); if(blob) { const reader = new FileReader(); const content = await new Promise(resolve=>{ reader.onload=()=>resolve(reader.result); reader.readAsDataURL(blob); }); exportData.dbFiles.push({ dbKey:node.dbKey, name:node.name, content:content }); } } else if(node.children) for(let child of node.children) await collectDBFiles(child); } await collectDBFiles(exportData.fileSystem); const jsonStr = JSON.stringify(exportData); const blob = new Blob([jsonStr], { type:'application/json' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href=url; a.download=`xp_backup_${new Date().toISOString().slice(0,19)}.xpbackup`; a.click(); URL.revokeObjectURL(url); alert('导出完成'); } async function importUserData() { const input = document.createElement('input'); input.type='file'; input.accept='.xpbackup,application/json'; input.onchange = async (e) => { const file = e.target.files[0]; const reader = new FileReader(); reader.onload = async (ev) => { try { const data = JSON.parse(ev.target.result); if(data.version!==1) throw new Error('不支持的备份版本'); if(!confirm('导入将覆盖当前用户的所有数据,是否继续?')) return; if(db) { const transaction = db.transaction([STORE_NAME],'readwrite'); const store = transaction.objectStore(STORE_NAME); store.clear(); } fileSystem = data.fileSystem; for(let dbFile of data.dbFiles) { const blob = await fetch(dbFile.content).then(r=>r.blob()); await saveFileToDB(dbFile.dbKey,blob); } saveFileSystem(); registry = data.registry; saveRegistry(); desktopShortcuts = data.shortcuts || []; // 为旧数据补充 ID desktopShortcuts = desktopShortcuts.map(s => { if (!s.id) s.id = generateShortcutId(); return s; }); desktop.style.backgroundImage = data.wallpaper ? `url('${data.wallpaper}')` : ''; if(currentUserId) { users[currentUserId].wallpaper = data.wallpaper; users[currentUserId].shortcuts = desktopShortcuts; users[currentUserId].files = JSON.parse(JSON.stringify(fileSystem)); saveUsers(); } renderDesktopIcons(); alert('导入成功,请重启系统以完全生效。'); startBootProgress(false); } catch(err) { alert('导入失败:'+err.message); } }; reader.readAsText(file); }; input.click(); } function saveShortcuts() { if(currentUserId) { users[currentUserId].shortcuts = desktopShortcuts; saveUsers(); } } // ===== 新增:桌面同步函数 ===== function syncDesktopShortcuts() { if (!currentUserRoot) { console.log('⚠️ 未登录,跳过同步'); return; } console.log('🔄 开始同步桌面快捷方式...'); // 获取当前用户的 Desktop 文件夹绝对路径 const desktopPath = currentUserRoot + '/Desktop'; console.log('🖥️ Desktop 文件夹路径:', desktopPath); const desktopFolder = getFolderByPath(desktopPath); if (!desktopFolder) { console.log('❌ 未找到 Desktop 文件夹'); return; } // 获取 Desktop 文件夹中所有文件/文件夹的名称 const desktopItems = new Set(); desktopFolder.children.forEach(item => { desktopItems.add(item.name); }); console.log('📋 Desktop 文件夹内容:', Array.from(desktopItems)); // 遍历现有桌面快捷方式,移除指向 Desktop 但文件已不存在的 let changed = false; for (let i = desktopShortcuts.length - 1; i >= 0; i--) { const shortcut = desktopShortcuts[i]; if (shortcut.fullPath && shortcut.fullPath.startsWith(desktopPath)) { const fileName = shortcut.fullPath.substring(shortcut.fullPath.lastIndexOf('/') + 1); if (!desktopItems.has(fileName)) { console.log('🗑️ 移除失效的快捷方式:', shortcut.name); desktopShortcuts.splice(i, 1); changed = true; } } } // 遍历 Desktop 文件夹,为每个文件创建对应的桌面快捷方式(如果不存在) desktopFolder.children.forEach(item => { const fullPath = desktopPath + '/' + item.name; const exists = desktopShortcuts.some(s => s.fullPath === fullPath); if (!exists) { const shortcutName = item.name.replace(/\.[^/.]+$/, '') || item.name; const emoji = item.type === 'folder' ? '📁' : (item.name.includes('.txt') ? '📄' : '📋'); console.log('➕ 创建新快捷方式:', shortcutName, '指向:', fullPath); desktopShortcuts.push({ id: generateShortcutId(), name: shortcutName, emoji: emoji, fullPath: fullPath, isFolder: item.type === 'folder', isWeb: false }); changed = true; } }); if (changed) { console.log('✅ 桌面快捷方式已更新,保存并重新渲染'); saveShortcuts(); renderDesktopIcons(); } else { console.log('✅ 桌面快捷方式已是最新状态'); } } function renderDesktopIcons() { const container = document.querySelector('.desktop-icons'); container.innerHTML = ''; builtinApps.forEach(app => { const icon = document.createElement('div'); icon.className = 'desktop-icon'; icon.innerHTML = `${app.emoji}${app.name}`; icon.addEventListener('click', () => { const action = app.action; if(action==='recycle') openRecycleBin(); else if(action==='paint') openPaint(); else if(action==='imageviewer') openImageViewer(); else if(action==='mediaplayer') openMediaPlayer(); else if(action==='minesweeper') openMinesweeper(); else if(action==='network') showNetworkNeighborhood(); else openApp(action); }); container.appendChild(icon); }); desktopShortcuts.forEach((shortcut, index) => { const icon = document.createElement('div'); icon.className = 'desktop-icon'; icon.innerHTML = `${shortcut.emoji || '📄'}${shortcut.name}`; icon.addEventListener('click', () => { if (shortcut.isWeb) { openEnhancedBrowser(shortcut.url); } else if (shortcut.isFolder) { let folderPath = shortcut.folderPath || (shortcut.folderName + '/' + shortcut.fileName); // 确保路径是绝对路径 if (!folderPath.startsWith('全部设备/') && !folderPath.startsWith('Users/')) { // 尝试转换为绝对路径 const rootChildren = ['系统','回收站','共享文档','Users']; if (rootChildren.includes(folderPath.split('/')[0])) { folderPath = '全部设备/本地磁盘 (C:)/' + folderPath; } else if (currentUserRoot && !folderPath.startsWith(currentUserRoot)) { folderPath = currentUserRoot + '/' + folderPath; } } // 尝试解析文件夹是否存在 const folder = getFolderByPath(folderPath); if (!folder) { alert(`文件夹"${shortcut.name}"不存在,快捷方式将自动删除。`); desktopShortcuts.splice(index, 1); saveShortcuts(); renderDesktopIcons(); return; } openFolderByPath(folderPath); } else if (shortcut.fullPath) { let fullPath = shortcut.fullPath; // 同样的路径归一化 if (!fullPath.startsWith('全部设备/') && !fullPath.startsWith('Users/')) { const firstPart = fullPath.split('/')[0]; const rootChildren = ['系统','回收站','共享文档','Users']; if (rootChildren.includes(firstPart)) { fullPath = '全部设备/本地磁盘 (C:)/' + fullPath; } else if (currentUserRoot && !fullPath.startsWith(currentUserRoot)) { fullPath = currentUserRoot + '/' + fullPath; } } const resolved = resolvePath(fullPath); if (resolved && resolved.file) { openFileInNewWindow(resolved.file); } else if (resolved && resolved.folder) { openFolderByPath(fullPath); } else { alert(`文件"${shortcut.name}"不存在,快捷方式将自动删除。`); desktopShortcuts.splice(index, 1); saveShortcuts(); renderDesktopIcons(); } } else { const folder = fileSystem.children.find(c => c.name === shortcut.folderName && c.type === 'folder'); if (folder) { const file = folder.children.find(f => f.name === shortcut.fileName); if (file) { openFileInNewWindow(file); } else { alert(`快捷方式指向的文件"${shortcut.fileName}"不存在,即将删除`); desktopShortcuts.splice(index, 1); saveShortcuts(); renderDesktopIcons(); } } else { alert(`文件夹"${shortcut.folderName}"不存在,快捷方式无效`); desktopShortcuts.splice(index, 1); saveShortcuts(); renderDesktopIcons(); } } }); container.appendChild(icon); }); } startButton.addEventListener('click', (e) => { e.stopPropagation(); startMenu.classList.toggle('active'); }); document.addEventListener('click', (e) => { if (!startButton.contains(e.target) && !startMenu.contains(e.target) && !allProgramsBtn.contains(e.target)) { startMenu.classList.remove('active'); } const wrapper = document.getElementById('submenu-wrapper'); if (wrapper && wrapper.classList.contains('active') && !wrapper.contains(e.target) && !allProgramsBtn.contains(e.target)) { closeAllProgramsMenu(); } }); document.querySelectorAll('#start-menu .menu-item:not(#all-programs-btn)').forEach(item => { item.addEventListener('click', (e) => { const app = item.dataset.app; if(app) openApp(app); startMenu.classList.remove('active'); }); }); // 关机按钮事件 document.getElementById('shutdown-btn').addEventListener('click', (e) => { e.stopPropagation(); startMenu.classList.remove('active'); showShutdownChoices(); }); // 注销按钮事件 document.getElementById('logout-btn').addEventListener('click', (e) => { e.stopPropagation(); startMenu.classList.remove('active'); switchUser(); }); shutdownOverlay.addEventListener('click', () => { location.reload(); // 直接刷新页面,显示完整启动过程 }); document.querySelectorAll('.quick-item').forEach(q => { q.addEventListener('click', () => { const app = q.dataset.app; openApp(app); }); }); function migrateOldUserFormat() { const raw = localStorage.getItem('xp_users'); if (!raw) return false; try { const parsed = JSON.parse(raw); // 如果没有 users 字段,说明还是旧格式 if (!parsed.users) { const newData = { users: {}, currentUserId: 'admin' }; // 将旧的 admin 和 guest 迁移到新结构 if (parsed.admin) { newData.users['admin'] = { id: 'admin', // 新增 id 字段 name: '管理员', avatar: '👤', // 默认头像 emoji isAdmin: true, ...parsed.admin }; } if (parsed.guest) { newData.users['guest'] = { id: 'guest', name: '访客', avatar: '👥', isAdmin: false, ...parsed.guest }; } localStorage.setItem('xp_users', JSON.stringify(newData)); return true; } return false; } catch(e) { console.warn('迁移旧用户格式失败', e); return false; } } function loadUsers() { migrateOldUserFormat(); // 确保数据格式兼容 const saved = localStorage.getItem('xp_users'); if (saved) { try { const parsed = JSON.parse(saved); if (parsed.users) { users = parsed.users; currentUserId = parsed.currentUserId || 'admin'; // 给可能缺失 id 的用户补充 id for (let key in users) { if (!users[key].id) users[key].id = key; if (!users[key].name) users[key].name = key; if (!users[key].avatar) users[key].avatar = '👤'; if (!users[key].shortcuts) users[key].shortcuts = []; if (!users[key].password) users[key].password = ''; // 为旧数据补充 ID users[key].shortcuts = (users[key].shortcuts || []).map(s => { if (!s.id) s.id = generateShortcutId(); return s; }); } return; } } catch(e) { console.warn('加载用户数据失败', e); } } // 如果没有数据,创建默认用户 const defaultUser = { id: 'admin', name: '管理员', avatar: '👤', isAdmin: true, wallpaper: '', files: JSON.parse(JSON.stringify(fileSystem)), shortcuts: [], password: '' }; users = { 'admin': defaultUser }; currentUserId = 'admin'; } // ====== 新增:显示欢迎界面 ====== function showWelcomeScreen(callback) { // 如果已经有欢迎界面,先移除 const existingWelcome = document.getElementById('welcome-screen'); if (existingWelcome) existingWelcome.remove(); const welcomeDiv = document.createElement('div'); welcomeDiv.id = 'welcome-screen'; welcomeDiv.style.position = 'fixed'; welcomeDiv.style.top = '0'; welcomeDiv.style.left = '0'; welcomeDiv.style.width = '100%'; welcomeDiv.style.height = '100%'; welcomeDiv.style.background = "url('imgs/login-bg.jpeg') center/cover no-repeat"; welcomeDiv.style.zIndex = '100000'; welcomeDiv.style.display = 'flex'; welcomeDiv.style.flexDirection = 'column'; welcomeDiv.style.alignItems = 'center'; welcomeDiv.style.justifyContent = 'center'; // 去掉 transition,改为直接显示/隐藏 welcomeDiv.innerHTML = `

欢迎使用

`; document.body.appendChild(welcomeDiv); // 3秒后直接移除,没有渐变 setTimeout(() => { welcomeDiv.remove(); if (callback) callback(); }, 3000); } // ====== 新增结束 ====== function showLoginScreen() { if(currentUserId) { users[currentUserId].files = JSON.parse(JSON.stringify(fileSystem)); users[currentUserId].wallpaper = desktop.style.backgroundImage.slice(5,-2)||''; users[currentUserId].shortcuts = desktopShortcuts; } saveUsers(); windows.forEach(w=>w.div.remove()); windows=[]; renderTaskbar(); const loginDiv = document.createElement('div'); loginDiv.id='loginScreen'; loginDiv.style.position='fixed'; loginDiv.style.top='0'; loginDiv.style.left='0'; loginDiv.style.width='100%'; loginDiv.style.height='100%'; loginDiv.style.background = "url('imgs/login-bg.jpeg') center/cover no-repeat"; loginDiv.style.zIndex='10000'; loginDiv.style.display='flex'; loginDiv.style.flexDirection='column'; loginDiv.style.alignItems='center'; loginDiv.style.justifyContent='center'; // 生成用户列表 let usersHtml = ''; for (let userId in users) { const user = users[userId]; usersHtml += `
${user.avatar || '👤'} ${user.name}
`; } loginDiv.innerHTML = `

Windows XP 登录

${usersHtml}
`; document.body.appendChild(loginDiv); const taskbar = document.getElementById('taskbar'); if (taskbar) taskbar.style.display = 'none'; loginDiv.querySelectorAll('[data-user]').forEach(el => { el.addEventListener('click', () => { const userId = el.dataset.user; const user = users[userId]; if(user.password && user.password !== '') { passwordOverlay.dataset.targetUser = userId; passwordTitle.innerText = `请输入 ${user.name} 密码`; passwordInput.value = ''; passwordOverlay.style.display = 'flex'; } else loginUser(userId); }); }); loginDiv.querySelector('#login-factory-reset').addEventListener('click', () => { if(confirm('恢复出厂设置将清除所有数据,确定吗?')) { factoryReset(); loginDiv.remove(); startBootProgress(false); } }); loginDiv.querySelector('#login-shutdown').addEventListener('click', () => { // 1. 先移除登录界面 loginDiv.remove(); // 2. 显示关机遮罩(强制设置 display:flex 确保显示) const shutdownOverlay = document.getElementById('shutdown-overlay'); shutdownOverlay.style.display = 'flex'; shutdownOverlay.classList.add('active'); // 3. 播放关机音效 playSystemSound('shutdown'); // 4. 更新关机文字(可选) shutdownOverlay.querySelector('div').innerText = "Windows XP 正在关机"; }); passwordSubmit.onclick = () => { const pwd = passwordInput.value; const targetUserId = passwordOverlay.dataset.targetUser; if(users[targetUserId].password === pwd) { passwordOverlay.style.display='none'; loginDiv.remove(); // 密码正确,直接登录(loginUser 内部会显示欢迎界面) loginUser(targetUserId); } else { alert('密码错误'); } }; passwordCancel.onclick = () => { passwordOverlay.style.display='none'; }; } function loginUser(userId) { currentUserId = userId; const user = users[userId]; // 设置当前用户根目录 const userFolderName = user.name; // 假设用户名与文件夹名一致 const userRootPath = '全部设备/本地磁盘 (C:)/Users/' + userFolderName; // 确保 Users 文件夹存在 let usersFolder = fileSystem.children.find(c => c.name === 'Users' && c.type === 'folder'); if (!usersFolder) { usersFolder = { name: 'Users', type: 'folder', children: [] }; fileSystem.children.push(usersFolder); saveFileSystem(); console.log('✅ 已创建 Users 文件夹'); } // 确保用户文件夹存在 createUserFolderStructure(userFolderName); // 如果不存在则创建 // 将当前用户根路径设置为 Users/用户名 currentUserRoot = userRootPath; // 不再使用 user.files,直接从全局 fileSystem 中定位用户文件夹 const userFolder = getFolderByPath(currentUserRoot); if (!userFolder) { // 如果用户文件夹不存在(可能被误删),重新创建 createUserFolderStructure(userFolderName); } // ---------- 加载壁纸(修复版V2:不再阻塞登录流程) ---------- // 1. 立即设置默认壁纸(同步执行,确保不会空白) if (user.wallpaper && user.wallpaper !== '') { desktop.style.backgroundImage = `url('${user.wallpaper}')`; } else { desktop.style.backgroundImage = `url('imgs/wallpaper.jpeg')`; } // 2. 异步尝试从系统文件夹加载壁纸(不阻塞后续的任何登录代码) const systemPath = '全部设备/本地磁盘 (C:)/系统'; const systemFolder = getFolderByPath(systemPath); if (systemFolder && systemFolder.children.length > 0) { const imageFile = systemFolder.children.find(f => f.type === 'file' && /\.(png|jpg|jpeg|gif|bmp|webp|apng)$/i.test(f.name) && f.dbKey ); if (imageFile) { (async () => { try { const blob = await getFileFromDB(imageFile.dbKey); if (blob) { const url = URL.createObjectURL(blob); desktop.style.backgroundImage = `url('${url}')`; if (users[currentUserId]) { users[currentUserId].wallpaper = url; saveUsers(); } } } catch (error) { console.warn('异步加载系统壁纸失败,继续使用已有壁纸', error); } })(); } } // ========== 壁纸加载修复结束 ========== desktopShortcuts = (user.shortcuts || []).map(s => { if (!s.id) s.id = generateShortcutId(); return s; }); // 确保标准用户文件夹存在 const userRoot = currentUserRoot; // 例如 "全部设备/本地磁盘 (C:)/Users/管理员" const ensureFolder = (folderName) => { const fullPath = userRoot + '/' + folderName; if (!getFolderByPath(fullPath)) { createFolderByPath(fullPath); } }; ensureFolder('Documents'); ensureFolder('Pictures'); ensureFolder('Music'); ensureFolder('Videos'); // 修复:确保用户Documents文件夹存在,这是创建快捷方式的常用位置 const docsPath = userRoot + '/Documents'; if (!getFolderByPath(docsPath)) { console.log('🔧 正在创建缺失的Documents文件夹:', docsPath); createFolderByPath(docsPath); } // ====== 修改:登录后先显示欢迎界面,然后才渲染桌面 ====== showWelcomeScreen(() => { // ====== 新增:初始化默认开机/关机音效 ====== (async function ensureDefaultSounds() { const systemFolder = getFolderByPath('全部设备/本地磁盘 (C:)/系统'); if (!systemFolder) return; const sounds = [ { fileName: 'startup.mp3', url: 'imgs/startup.mp3' }, { fileName: 'shutdown.mp3', url: 'imgs/shutdown.mp3' } ]; for (let sound of sounds) { const existingSound = systemFolder.children.find(f => f.name === sound.fileName && f.type === 'file'); if (!existingSound) { try { const response = await fetch(sound.url); if (!response.ok) continue; // 如果 imgs 里没有这个文件,跳过 const blob = await response.blob(); const dbKey = Date.now() + '_' + 'default_' + Math.random(); await saveFileToDB(dbKey, blob); systemFolder.children.push({ name: sound.fileName, type: 'file', dbKey: dbKey }); console.log(`成功导入默认音效: ${sound.fileName}`); } catch (error) { console.warn(`导入默认音效 ${sound.fileName} 失败:`, error); } } } saveFileSystem(); })(); // ====== 新增代码结束 ====== // ====== 新增:确保 Documents 文件夹里有默认文件 ====== const docsFolder = getFolderByPath('Documents'); if (docsFolder) { // 检查 readme.txt 是否存在,不存在则自动创建 if (!docsFolder.children.some(f => f.name === 'readme.txt')) { docsFolder.children.push({ name: 'readme.txt', type: 'file', content: '欢迎使用Windows XP 触控模拟' }); } // 检查 hello.html 是否存在,不存在则自动创建 if (!docsFolder.children.some(f => f.name === 'hello.html')) { docsFolder.children.push({ name: 'hello.html', type: 'file', content: '

内嵌HTML应用

您可以在窗口中查看我

' }); } // 保存文件系统 saveFileSystem(); } // ====== 新增代码结束 ====== // 更新开始菜单头像和名字 const startAvatar = document.getElementById('start-avatar'); const startUsername = document.getElementById('start-username'); if (startAvatar) startAvatar.textContent = user.avatar || '👤'; if (startUsername) startUsername.textContent = user.name; // 注销功能 const logoutBtn = document.getElementById('logout-btn'); const logoutText = logoutBtn?.nextElementSibling; // 获取旁边的文字 const performLogout = () => { document.getElementById('start-menu').classList.remove('active'); if (typeof switchUser === 'function') { switchUser(); } else { showLoginScreen(); } }; logoutBtn?.addEventListener('click', performLogout); logoutText?.addEventListener('click', performLogout); // 关机功能 const shutdownBtn = document.getElementById('shutdown-btn'); const shutdownText = shutdownBtn?.nextElementSibling; const performShutdown = () => { document.getElementById('start-menu').classList.remove('active'); showShutdownChoices(); }; shutdownBtn?.addEventListener('click', performShutdown); shutdownText?.addEventListener('click', performShutdown); renderDesktopIcons(); // === 新增:登录时同步桌面快捷方式 === console.log('🚀 登录完成,开始同步桌面快捷方式'); syncDesktopShortcuts(); updateStartMenuLeft(); // === 新增:加载用户主题设置 === const savedTheme = getRegistryValue('HKEY_CURRENT_USER\\Control Panel\\Desktop', 'Theme') || 'blue'; applyTheme(savedTheme); const loginDiv = document.getElementById('loginScreen'); if(loginDiv) loginDiv.remove(); performAutoBackup(); const taskbar = document.getElementById('taskbar'); if (taskbar) taskbar.style.display = 'flex'; // 开机自动运行 .reg 中的 HTML 应用 autoRunAtStartup(); }); // ====== 修改结束 ====== } // ========== 新功能:显示关机选择框 ========== function showShutdownChoices() { // ========== 修复:更安全地保存任务栏状态 ========== const taskbar = document.getElementById('taskbar'); if (taskbar) { // 使用 getComputedStyle 确保获取到真正的显示状态,而不是被之前代码污染的状态 taskbar._origDisplay = window.getComputedStyle(taskbar).display; taskbar.style.display = 'none'; } // ========== 修复结束 ========== const shutdownOverlay = document.getElementById('shutdown-overlay'); shutdownOverlay.style.display = 'flex'; shutdownOverlay.classList.add('active'); const choiceOverlay = document.getElementById('shutdown-choice-overlay'); choiceOverlay.classList.add('active'); } // ========== 绑定三个按钮 ========== // 1. 关机 document.getElementById('choice-shutdown').addEventListener('click', () => { playSystemSound('shutdown'); // 关闭所有窗口 windows.forEach(w => w.div.remove()); windows = []; renderTaskbar(); // 隐藏选择框 document.getElementById('shutdown-choice-overlay').classList.remove('active'); // 修改黑白背景为最终关机画面 const overlay = document.getElementById('shutdown-overlay'); overlay.querySelector('div').innerText = "正在关闭 Windows XP..."; overlay.querySelector('.shutdown-text').innerText = "⏻"; }); // 2. 重启 document.getElementById('choice-restart').addEventListener('click', () => { location.reload(); }); // 3. 待机 document.getElementById('choice-standby').addEventListener('click', () => { alert('待机功能模拟。'); document.getElementById('shutdown-choice-overlay').classList.remove('active'); const overlay = document.getElementById('shutdown-overlay'); overlay.classList.remove('active'); overlay.style.display = 'none'; // ========== 修复:强制恢复任务栏显示 ========== const taskbar = document.getElementById('taskbar'); if (taskbar) { taskbar.style.display = 'flex'; delete taskbar._origDisplay; // 清理保存的状态,避免下次出错 } // ========== 修复结束 ========== }); // 4. 取消 document.getElementById('choice-cancel').addEventListener('click', () => { document.getElementById('shutdown-choice-overlay').classList.remove('active'); const overlay = document.getElementById('shutdown-overlay'); overlay.classList.remove('active'); overlay.style.display = 'none'; // ========== 修复:强制恢复任务栏显示 ========== const taskbar = document.getElementById('taskbar'); if (taskbar) { taskbar.style.display = 'flex'; delete taskbar._origDisplay; // 清理保存的状态,避免下次出错 } // ========== 修复结束 ========== }); startBootProgress(false); function switchUser() { users[currentUserId].files = JSON.parse(JSON.stringify(fileSystem)); users[currentUserId].wallpaper = desktop.style.backgroundImage.slice(5,-2)||''; users[currentUserId].shortcuts = desktopShortcuts; saveUsers(); showLoginScreen(); } setTimeout(() => { const startRight = document.querySelector('.start-right'); if(startRight) { const divider = document.createElement('div'); divider.className='menu-divider'; startRight.appendChild(divider); const switchItem = document.createElement('div'); switchItem.className='menu-item'; switchItem.innerHTML='🔄 切换用户'; switchItem.addEventListener('click',(e)=>{ e.stopPropagation(); switchUser(); startMenu.classList.remove('active'); }); startRight.appendChild(switchItem); } },1000); window.addEventListener('beforeunload', () => { if(currentUserId) { let wallpaperUrl = desktop.style.backgroundImage; if(wallpaperUrl && wallpaperUrl.startsWith('url(')) users[currentUserId].wallpaper = wallpaperUrl.slice(5,-2); else users[currentUserId].wallpaper = ''; users[currentUserId].shortcuts = desktopShortcuts; users[currentUserId].files = JSON.parse(JSON.stringify(fileSystem)); saveUsers(); } // ====== 新增:保存关联数据 ====== saveFileAssociations(); saveCustomUploadOptions(); // ====== 新增结束 ====== }); desktopShortcuts = (users[currentUserId]?.shortcuts || []).map(s => { if (!s.id) s.id = generateShortcutId(); return s; }); renderDesktopIcons(); openDB().catch(console.error); // ========== 长按右键菜单功能(修复版:支持桌面空白处 + 应用自定义菜单合并) ========== let longPressTimer = null; let longPressTriggered = false; let touchStartX = 0, touchStartY = 0; const LONG_PRESS_DELAY = 400; const MOVE_THRESHOLD = 10; let clipboard = { type: null, data: null }; document.addEventListener('contextmenu', (e) => { e.preventDefault(); const target = e.target; const x = e.clientX; const y = e.clientY; // ---- 1. 桌面空白处 ---- const isDesktopBlank = (target === desktop || target.classList.contains('desktop-icons') || (target.parentElement === desktop && !target.closest('.desktop-icon, .window, #taskbar, #start-menu'))); if (isDesktopBlank) { showDesktopContextMenu(x, y); return; } // ---- 2. 文件管理器空白处(新增) ---- const contentArea = target.closest('.window-content'); if (contentArea && !target.closest('[data-file-path]')) { const currentPath = contentArea.getAttribute('data-current-path'); if (currentPath) { showFolderContextMenu(currentPath, x, y); return; } } // ---- 3. 其他可交互元素(桌面图标、文件/文件夹、标题栏、开始菜单、任务栏、iframe) ---- const actionable = target.closest('.desktop-icon, [data-file-path], .window-header, #start-menu .menu-item, .task-item, iframe'); if (actionable) { showContextMenu(actionable, x, y); } }); function onTouchStart(e) { const touch = e.touches[0]; touchStartX = touch.clientX; touchStartY = touch.clientY; longPressTriggered = false; if (e.target.closest('.minesweeper-game')) return; const target = e.target; const isDesktopBlank = (target === desktop || target.classList.contains('desktop-icons') || (target.parentElement === desktop && !target.closest('.desktop-icon, .window, #taskbar, #start-menu'))); if (isDesktopBlank) { longPressTimer = setTimeout(() => { longPressTriggered = true; showDesktopContextMenu(touch.clientX, touch.clientY); e.preventDefault(); }, LONG_PRESS_DELAY); } else { const actionable = target.closest('.desktop-icon, .file-open, .explorer-item, .window-header, #start-menu .menu-item, .task-item'); if (!actionable) return; longPressTimer = setTimeout(() => { longPressTriggered = true; showContextMenu(actionable, touch.clientX, touch.clientY); e.preventDefault(); }, LONG_PRESS_DELAY); } } function onTouchMove(e) { if (!longPressTimer) return; const touch = e.touches[0]; const dx = Math.abs(touch.clientX - touchStartX); const dy = Math.abs(touch.clientY - touchStartY); if (dx > MOVE_THRESHOLD || dy > MOVE_THRESHOLD) { clearLongPress(); } } function onTouchEnd(e) { clearLongPress(); } function clearLongPress() { if (longPressTimer) { clearTimeout(longPressTimer); longPressTimer = null; } } // 鼠标左键长按检测(电脑端) let mouseLongPressTimer = null; let mouseLongPressTriggered = false; let mouseStartX = 0, mouseStartY = 0; function onMouseDown(e) { // 只响应左键 if (e.button !== 0) return; // 如果点击在扫雷游戏内,不处理 if (e.target.closest('.minesweeper-game')) return; mouseStartX = e.clientX; mouseStartY = e.clientY; mouseLongPressTriggered = false; const target = e.target; const isDesktopBlank = (target === desktop || target.classList.contains('desktop-icons') || (target.parentElement === desktop && !target.closest('.desktop-icon, .window, #taskbar, #start-menu'))); if (isDesktopBlank) { mouseLongPressTimer = setTimeout(() => { mouseLongPressTriggered = true; showDesktopContextMenu(e.clientX, e.clientY); e.preventDefault(); }, LONG_PRESS_DELAY); } else { const actionable = target.closest('.desktop-icon, .file-open, .explorer-item, .window-header, #start-menu .menu-item, .task-item'); if (!actionable) return; mouseLongPressTimer = setTimeout(() => { mouseLongPressTriggered = true; showContextMenu(actionable, e.clientX, e.clientY); e.preventDefault(); }, LONG_PRESS_DELAY); } } function onMouseMove(e) { if (!mouseLongPressTimer) return; const dx = Math.abs(e.clientX - mouseStartX); const dy = Math.abs(e.clientY - mouseStartY); if (dx > MOVE_THRESHOLD || dy > MOVE_THRESHOLD) { clearMouseLongPress(); } } function onMouseUp(e) { clearMouseLongPress(); } function clearMouseLongPress() { if (mouseLongPressTimer) { clearTimeout(mouseLongPressTimer); mouseLongPressTimer = null; } } document.addEventListener('click', (e) => { if (longPressTriggered || mouseLongPressTriggered) { e.stopPropagation(); e.preventDefault(); longPressTriggered = false; mouseLongPressTriggered = false; } }, true); function getAppMenuItems(iframe) { if (!window._appContextMenus) return []; for (let [appId, data] of window._appContextMenus.entries()) { if (data.iframe === iframe) return data.items || []; } return []; } function showDesktopContextMenu(x, y) { const existingMenu = document.querySelector('.context-menu'); if (existingMenu) existingMenu.remove(); const desktopMenuItems = [ { label: '刷新', action: () => { syncDesktopShortcuts(); } }, // 改为调用同步函数 { label: '粘贴', action: () => pasteToDesktop() }, { label: '新建文件夹', action: () => createFolderOnDesktop() }, { label: '新建文本文档', action: () => newTextFile() }, { label: '更改壁纸', action: () => uploadWallpaper() }, { label: '排列图标', action: () => sortDesktopIcons() }, { label: '属性', action: () => showDesktopProperties() } ]; createContextMenu(desktopMenuItems, x, y); } function createContextMenu(items, x, y) { const menuDiv = document.createElement('div'); menuDiv.className = 'context-menu'; menuDiv.style.left = x + 'px'; menuDiv.style.top = y + 'px'; items.forEach(item => { const btn = document.createElement('div'); btn.className = 'context-menu-item'; btn.textContent = item.label; btn.addEventListener('click', (e) => { e.stopPropagation(); item.action(); menuDiv.remove(); }); menuDiv.appendChild(btn); }); document.body.appendChild(menuDiv); const rect = menuDiv.getBoundingClientRect(); if (rect.right > window.innerWidth) menuDiv.style.left = (window.innerWidth - rect.width - 10) + 'px'; if (rect.bottom > window.innerHeight) menuDiv.style.top = (window.innerHeight - rect.height - 10) + 'px'; const closeHandler = (e) => { if (!menuDiv.contains(e.target)) { menuDiv.remove(); document.removeEventListener('click', closeHandler); document.removeEventListener('touchstart', closeHandler); } }; setTimeout(() => { document.addEventListener('click', closeHandler); document.addEventListener('touchstart', closeHandler); }, 0); } async function pasteToDesktop() { if (!currentUserRoot) { alert("未登录"); return; } if (!clipboard.data) { alert('剪贴板为空'); return; } // 优先粘贴到桌面文件夹,不存在则回退到Documents const desktopFolder = getFolderByPath(currentUserRoot + '/Desktop'); const targetFolder = desktopFolder || getFolderByPath(currentUserRoot + '/Documents'); if (!targetFolder) { alert("无法找到目标文件夹"); return; } const srcFile = clipboard.data; if (targetFolder.children.some(f => f.name === srcFile.name)) { alert('目标文件夹中已存在同名文件'); return; } const newFile = JSON.parse(JSON.stringify(srcFile)); if (newFile.dbKey) { const blob = await getFileFromDB(srcFile.dbKey); if (blob) { const newDbKey = Date.now() + '_' + Math.random(); await saveFileToDB(newDbKey, blob); newFile.dbKey = newDbKey; delete newFile.content; } } targetFolder.children.push(newFile); saveFileSystem(); // 如果粘贴到桌面文件夹,需要同步桌面快捷方式 if (desktopFolder) { syncDesktopShortcuts(); } if (clipboard.type === 'cut') { const srcParent = getParentFolder(srcFile); if (srcParent) { const idx = srcParent.children.findIndex(f => f === srcFile); if (idx !== -1) { if (srcFile.dbKey) await deleteFileFromDB(srcFile.dbKey); srcParent.children.splice(idx, 1); saveFileSystem(); } } clipboard = { type: null, data: null }; } alert(`已粘贴到"${targetFolder.name}"`); renderDesktopIcons(); } function createFolderOnDesktop() { if (!currentUserRoot) { alert("未登录"); return; } const name = prompt('文件夹名称:', '新建文件夹'); if (name) { const myDocs = getFolderByPath(currentUserRoot + '/Documents'); if (myDocs && !myDocs.children.find(c => c.name === name)) { myDocs.children.push({ name, type: 'folder', children: [] }); saveFileSystem(); alert(`文件夹“${name}”已创建在“我的文档”中`); if (confirm('是否在桌面创建快捷方式?')) { const absolutePath = currentUserRoot ? currentUserRoot + '/Documents/' + name : 'Documents/' + name; desktopShortcuts.push({ id: generateShortcutId(), name: name, emoji: '📁', fullPath: absolutePath, isFolder: true, isWeb: false }); saveShortcuts(); renderDesktopIcons(); } } else alert('创建失败,可能同名'); } } function sortDesktopIcons() { builtinApps.sort((a,b) => a.name.localeCompare(b.name)); desktopShortcuts.sort((a,b) => a.name.localeCompare(b.name)); renderDesktopIcons(); alert('图标已按名称排序'); } function showDesktopProperties() { createWindow('显示属性', `
分辨率: 1024x768
主题: ${getRegistryValue('HKEY_CURRENT_USER\\Control Panel\\Desktop', 'Theme') || 'blue'}
`, 350, 200); setTimeout(() => { document.getElementById('openDisplay')?.addEventListener('click', showDisplaySettings); }, 50); } function getParentFolder(file) { function findParent(node, target) { if (node.type === 'folder' && node.children) { if (node.children.includes(target)) return node; for (let child of node.children) { if (child.type === 'folder') { const res = findParent(child, target); if (res) return res; } } } return null; } return findParent(fileSystem, file); } // 文件夹重命名函数 function renameFolder(fullPath, oldName, parentPath) { const newName = prompt('请输入新文件夹名称:', oldName); if (newName && newName !== oldName) { const parentFolder = getFolderByPath(parentPath); if (parentFolder) { const folder = parentFolder.children.find(c => c.name === oldName && c.type === 'folder'); if (folder) { if (parentFolder.children.some(c => c.name === newName)) { alert('同名文件夹已存在'); return; } folder.name = newName; saveFileSystem(); // 刷新当前窗口 const currentWindow = document.querySelector(`[data-current-path="${parentPath}"]`); if (currentWindow) { const folderObj = getFolderByPath(parentPath); if (folderObj) { const win = currentWindow.closest('.window'); const contentDiv = win.querySelector('.window-content'); contentDiv.innerHTML = ''; renderFolderContent(folderObj, contentDiv, parentPath); } } } } } } // 文件夹删除函数 // 删除文件夹(移动到回收站) async function deleteFolderItem(fullPath, folderName, parentPath) { if (!confirm(`确定要将文件夹"${folderName}"删除并移到回收站吗?`)) return; const parentFolder = getFolderByPath(parentPath); if (!parentFolder) { alert('无法找到父文件夹'); return; } const idx = parentFolder.children.findIndex(c => c.name === folderName && c.type === 'folder'); if (idx === -1) { alert('文件夹不存在'); return; } const folder = parentFolder.children[idx]; const success = await moveToRecycleBin(folder, parentFolder, parentPath); if (success) { alert('文件夹已移至回收站'); // 刷新窗口 const currentWin = findWindowByPath(parentPath); if (currentWin) { currentWin.div.querySelector('[data-action="close"]')?.click(); openFolderByPath(parentPath); } } else { alert('删除失败'); } } function showContextMenu(target, x, y) { const existingMenu = document.querySelector('.context-menu'); if (existingMenu) existingMenu.remove(); let menuItems = []; // 1. 桌面快捷方式 if (target.classList.contains('desktop-icon')) { const shortcutName = target.querySelector('span:last-child')?.innerText; menuItems = [ { label: '打开', action: () => target.click() }, { label: '删除', action: () => deleteDesktopShortcut(target, shortcutName) }, { label: '属性', action: () => showProperties('桌面快捷方式', shortcutName) } ]; } // 2. 文件/文件夹(网格视图和列表视图通用)—— 关键修改:检测 data-file-path else if (target.closest('[data-file-path]')) { const fileItem = target.closest('[data-file-path]'); if (!fileItem) return; const fullPath = fileItem.getAttribute('data-file-path'); const type = fileItem.getAttribute('data-file-type'); const name = fileItem.getAttribute('data-file-name'); // 获取父文件夹路径 let folderPath = ''; if (fullPath) { const lastSlash = fullPath.lastIndexOf('/'); if (lastSlash !== -1) { folderPath = fullPath.substring(0, lastSlash); } else { folderPath = ''; } } if (type === 'folder') { // 文件夹右键菜单 menuItems = [ { label: '打开', action: () => openFolderByPath(fullPath) }, { label: '复制', action: () => { clipboard = { type: 'copy', data: { name, type: 'folder', fullPath } }; alert(`已复制文件夹:${name}`); } }, { label: '剪切', action: () => { clipboard = { type: 'cut', data: { name, type: 'folder', fullPath } }; alert(`已剪切文件夹:${name}`); } }, { label: '粘贴', action: () => pasteFile(folderPath) }, { label: '重命名', action: () => renameFolder(fullPath, name, folderPath) }, { label: '删除', action: () => deleteFolderItem(fullPath, name, folderPath) }, { label: '属性', action: () => alert(`文件夹属性\n名称:${name}\n位置:${folderPath}`) }, { label: '创建桌面快捷方式', action: () => createDesktopShortcutFromMenu({ name, type: 'folder', fullPath }, folderPath) } ]; } else { // 文件右键菜单 const resolved = resolvePath(fullPath); const fileObj = resolved?.file; if (!fileObj) return; menuItems = [ { label: '打开', action: () => openFileInNewWindow(fileObj) }, { label: '复制', action: () => { clipboard = { type: 'copy', data: fileObj }; alert(`已复制:${fileObj.name}`); } }, { label: '剪切', action: () => { clipboard = { type: 'cut', data: fileObj }; alert(`已剪切:${fileObj.name}`); } }, { label: '粘贴', action: () => pasteFile(folderPath) }, { label: '重命名', action: () => renameFile(fileObj, folderPath) }, { label: '删除', action: () => deleteFileItem(fileObj, folderPath) }, { label: '属性', action: () => showFileProperties(fileObj) }, { label: '创建桌面快捷方式', action: () => createDesktopShortcutFromMenu(fileObj, folderPath) } ]; } } // 3. 窗口标题栏 else if (target.closest('.window-header')) { const win = target.closest('.window'); menuItems = [ { label: '关闭', action: () => win.querySelector('[data-action="close"]')?.click() }, { label: '最大化', action: () => win.querySelector('[data-action="max"]')?.click() }, { label: '最小化', action: () => win.querySelector('[data-action="min"]')?.click() }, { label: '置顶', action: () => { win.style.zIndex = nextZ++; alert('窗口已置顶'); } } ]; } // 4. 开始菜单项 else if (target.closest('#start-menu .menu-item')) { const menuItem = target.closest('.menu-item'); const appName = menuItem.dataset.app; menuItems = [ { label: '打开', action: () => { if (appName) openApp(appName); } }, { label: '固定到开始菜单', action: () => alert('固定到开始菜单功能模拟') } ]; } // 5. 任务栏按钮 else if (target.closest('.task-item')) { const taskBtn = target.closest('.task-item'); const taskText = taskBtn.querySelector('span:last-child')?.innerText; const winObj = windows.find(w => w.title === taskText); if (winObj) { menuItems = [ { label: '关闭窗口', action: () => winObj.div.querySelector('[data-action="close"]')?.click() }, { label: '最小化/还原', action: () => { if (winObj.minimized || winObj.div.style.display === 'none') { winObj.div.style.display = 'flex'; winObj.minimized = false; } else { winObj.div.style.display = 'none'; winObj.minimized = true; } renderTaskbar(); } } ]; } } // 6. iframe 中的应用自定义菜单 else if (target.closest('iframe')) { const iframe = target.closest('iframe'); const appItems = getAppMenuItems(iframe); if (appItems.length) { appItems.forEach(item => { menuItems.push({ label: item.label, action: () => { iframe.contentWindow.postMessage({ type: 'contextMenuCallback', callbackId: item.callbackId }, '*'); } }); }); if (menuItems.length) { menuItems.unshift({ label: '— 应用菜单 —', action: () => {} }); } } } if (menuItems.length === 0) return; createContextMenu(menuItems, x, y); } function deleteDesktopShortcut(iconEl, name) { // 🔁 改用精确的 ID 查找(通过 DOM 元素获取) const shortcutId = iconEl.dataset.shortcutId; if (shortcutId) { const index = desktopShortcuts.findIndex(s => s.id === shortcutId); if (index !== -1) { const shortcut = desktopShortcuts[index]; const recycleBin = getFolderByPath('全部设备/本地磁盘 (C:)/回收站'); if (recycleBin) { const shortcutFile = { name: shortcut.name + '.lnk', type: 'file', content: `[快捷方式]\n目标路径=${shortcut.fullPath || ''}\n是否文件夹=${shortcut.isFolder || false}`, originalFolder: '桌面' }; recycleBin.children.push(shortcutFile); saveFileSystem(); console.log('🗑️ 快捷方式已移至回收站:', shortcut.name); } desktopShortcuts.splice(index, 1); saveShortcuts(); renderDesktopIcons(); alert('快捷方式已删除并移至回收站'); return; } } // 备用:使用名称查找(仅当无 ID 时) const index = desktopShortcuts.findIndex(s => s.name === name); if (index !== -1) { const shortcut = desktopShortcuts[index]; const recycleBin = getFolderByPath('全部设备/本地磁盘 (C:)/回收站'); if (recycleBin) { const shortcutFile = { name: shortcut.name + '.lnk', type: 'file', content: `[快捷方式]\n目标路径=${shortcut.fullPath || ''}\n是否文件夹=${shortcut.isFolder || false}`, originalFolder: '桌面' }; recycleBin.children.push(shortcutFile); saveFileSystem(); console.log('🗑️ 快捷方式已移至回收站:', shortcut.name); } desktopShortcuts.splice(index, 1); saveShortcuts(); renderDesktopIcons(); alert('快捷方式已删除并移至回收站'); } } function showProperties(type, name) { alert(`${type}属性\n名称:${name}\n位置:桌面\n大小:未知`); } // ====== 新增:文件夹空白处右键菜单 ====== function showFolderContextMenu(folderPath, x, y) { const items = [ { label: '📄 新建文本文档', action: async () => { const name = prompt('请输入文件名:', '新建文本.txt'); if (name) { const fullPath = folderPath ? folderPath + '/' + name : name; const success = await writeFileByPath(fullPath, ''); if (success) { alert('✅ 文件已创建'); refreshFolderWindow(folderPath); } else { alert('❌ 创建失败,请检查路径或权限'); } } } }, { label: '📁 新建文件夹', action: () => { const name = prompt('请输入文件夹名称:', '新建文件夹'); if (name) { const fullPath = folderPath ? folderPath + '/' + name : name; const success = createFolderByPath(fullPath); if (success) { alert('✅ 文件夹已创建'); refreshFolderWindow(folderPath); } else { alert('❌ 创建失败,请检查路径或权限'); } } } }, { label: '📋 粘贴', action: () => pasteFile(folderPath) }, { label: '🔄 刷新', action: () => refreshFolderWindow(folderPath) }, { label: '📊 属性', action: () => { const folder = getFolderByPath(folderPath); if (folder) { alert(`文件夹属性\n名称:${folder.name}\n路径:${folderPath}\n子项数:${folder.children.length}`); } else { alert('文件夹不存在'); } } }, { label: '📌 排序(按名称)', action: () => { const folder = getFolderByPath(folderPath); if (folder) { folder.children.sort((a, b) => a.name.localeCompare(b.name)); saveFileSystem(); refreshFolderWindow(folderPath); alert('已按名称排序'); } } } ]; createContextMenu(items, x, y); } // ====== 新增:刷新文件夹窗口 ====== function refreshFolderWindow(folderPath) { const win = findWindowByPath(folderPath); if (win) { const folder = getFolderByPath(folderPath); if (folder) { // 关闭旧窗口,打开新窗口刷新视图 win.div.querySelector('[data-action="close"]')?.click(); openFolder(folder, folderPath); } } } // ====== 优化:findWindowByPath 函数 ====== function findWindowByPath(path) { // 将 path 归一化为绝对路径 let normalized = path; if (!normalized.startsWith('全部设备/') && !normalized.startsWith(currentUserRoot)) { if (currentUserRoot) { normalized = currentUserRoot + '/' + normalized; } } for (let win of windows) { const content = win.div.querySelector('.window-content'); if (content) { const currentPath = content.getAttribute('data-current-path'); if (currentPath && (currentPath === normalized || currentPath.startsWith(normalized + '/'))) { return win; } } } return null; } async function pasteFile(targetFolderPath) { if (!clipboard.data) { alert('剪贴板为空'); return; } if (!targetFolderPath) { alert('无法确定目标文件夹'); return; } const targetFolder = getFolderByPath(targetFolderPath); if (!targetFolder) { alert('目标文件夹不存在'); return; } const srcFile = clipboard.data; if (targetFolder.children.some(f => f.name === srcFile.name)) { alert('目标文件夹中已存在同名文件'); return; } const newFile = JSON.parse(JSON.stringify(srcFile)); if (newFile.dbKey) { const blob = await getFileFromDB(srcFile.dbKey); if (blob) { const newDbKey = Date.now() + '_' + Math.random(); await saveFileToDB(newDbKey, blob); newFile.dbKey = newDbKey; delete newFile.content; } } targetFolder.children.push(newFile); saveFileSystem(); if (clipboard.type === 'cut') { const srcParent = getParentFolder(srcFile); if (srcParent) { const idx = srcParent.children.findIndex(f => f === srcFile); if (idx !== -1) { if (srcFile.dbKey) await deleteFileFromDB(srcFile.dbKey); srcParent.children.splice(idx, 1); saveFileSystem(); } } clipboard = { type: null, data: null }; } alert('粘贴成功'); refreshMyDocsWindow(); // === 新增:如果粘贴到桌面文件夹,触发桌面同步 === const desktopPath = currentUserRoot + '/Desktop'; if (targetFolderPath === desktopPath) { syncDesktopShortcuts(); } const targetWin = findWindowByPath(targetFolderPath); if (targetWin) { const folder = getFolderByPath(targetFolderPath); if (folder) openFolder(folder, targetFolderPath); targetWin.div.querySelector('[data-action="close"]')?.click(); openFolder(folder, targetFolderPath); } } function findWindowByPath(path) { // 1. 先尝试解析传入的路径,获取其完整路径 let resolvedPath = null; // 如果 path 已经是绝对路径,直接用 if (typeof path === 'string' && (path.startsWith('全部设备/') || path.startsWith(currentUserRoot))) { resolvedPath = path; } else if (typeof path === 'string') { // 如果是相对路径(如 "Documents"),拼接到当前用户根下 const folder = getFolderByPath(path); // 如果能找到这个文件夹,获取它的完整路径 if (folder) { const parts = []; let current = folder; while (current && current.name && current !== fileSystem) { parts.unshift(current.name); // 尝试找到父节点(这里简化处理,通过遍历fileSystem反向查找比较麻烦) // 所以我们直接用 `currentUserRoot` 拼接: if (currentUserRoot) { resolvedPath = currentUserRoot + '/' + path; break; } // 如果找不到根,就回退 break; } if (parts.length > 0) { resolvedPath = parts.join('/'); } } } // 如果解析不出完整路径,就回退到原路径 if (!resolvedPath) resolvedPath = path; // 2. 遍历所有窗口,匹配其 `data-current-path` 属性 for (let win of windows) { const content = win.div.querySelector('.window-content'); if (content) { const currentPath = content.getAttribute('data-current-path'); // 如果窗口记录的路径与解析后的路径相等,或者它是子文件夹(比如在Documents里删文件,需要刷新Documents窗口) if (currentPath && (currentPath === resolvedPath || currentPath.startsWith(resolvedPath + '/'))) { return win; } } } return null; } function findWindowByTitle(title) { for (let win of windows) { // 获取窗口标题:从 header 中提取 const header = win.div.querySelector('.window-header'); if (header) { const titleEl = header.querySelector('.window-title'); if (titleEl && titleEl.textContent.includes(title)) { return win; } } // 对于无边框窗口,通过 id 匹配 if (win.title === title) return win; } return null; } async function renameFile(file, folderPath) { if (!file) return; const newName = prompt('请输入新文件名', file.name); if (newName && newName !== file.name) { const folder = getFolderByPath(folderPath); if (folder && !folder.children.some(f => f.name === newName)) { file.name = newName; saveFileSystem(); // === 新增:如果重命名的文件在 Desktop 文件夹中,同步桌面 === if (folderPath.includes('/Desktop')) { console.log('✏️ 在 Desktop 文件夹中重命名文件,触发桌面同步'); syncDesktopShortcuts(); } // === 新增结束 === alert('重命名成功'); refreshMyDocsWindow(); const win = findWindowByPath(folderPath); if (win) { const f = getFolderByPath(folderPath); if (f) openFolder(f, folderPath); win.div.querySelector('[data-action="close"]')?.click(); openFolder(f, folderPath); } } else { alert('同名文件已存在'); } } } // ====== 新增:移动文件/文件夹到回收站(递归处理) ====== async function moveToRecycleBin(item, parentFolder, parentPath) { // 1. 确保回收站存在 let recycleBin = getFolderByPath('全部设备/本地磁盘 (C:)/回收站'); if (!recycleBin) { const localDisk = getFolderByPath('全部设备/本地磁盘 (C:)'); if (localDisk) { recycleBin = { name: '回收站', type: 'folder', children: [] }; localDisk.children.push(recycleBin); saveFileSystem(); } else { return false; } } // 2. 如果是文件夹,递归处理所有子项 if (item.type === 'folder') { // 从父文件夹中移除该文件夹(先移除,避免递归时再次遍历) const idx = parentFolder.children.findIndex(c => c === item); if (idx !== -1) parentFolder.children.splice(idx, 1); // 在回收站中创建一个同名文件夹 const recycleFolder = { name: item.name, type: 'folder', children: [], originalFolder: parentPath }; recycleBin.children.push(recycleFolder); // 递归移动所有子文件/子文件夹 for (let child of item.children) { await moveToRecycleBin(child, item, parentPath + '/' + item.name); } saveFileSystem(); return true; } // 3. 如果是文件 else if (item.type === 'file') { const idx = parentFolder.children.findIndex(c => c === item); if (idx === -1) return false; // 从原位置移除 parentFolder.children.splice(idx, 1); // 移入回收站(保留 dbKey,不删除数据) recycleBin.children.push({ ...item, originalFolder: parentPath }); saveFileSystem(); return true; } return false; } // ====== 重新设计的 deleteFileItem,不依赖外部的 folderPath 和 file 对象 ====== async function deleteFileItem(file, fullPath) { if (!file) return; if (confirm(`确定要删除“${file.name}”并移到回收站吗?`)) { const folder = getFolderByPath(fullPath); if (!folder) { alert('文件夹不存在'); return; } const srcParent = getParentFolder(file); if (!srcParent) { alert('无法找到父文件夹'); return; } // ✅ 使用 moveToRecycleBin 将文件移到回收站 const success = await moveToRecycleBin(file, srcParent, fullPath); if (success) { // 如果删除的是桌面文件夹中的项,同步桌面快捷方式 if (fullPath.includes('/Desktop')) { syncDesktopShortcuts(); } alert('已移至回收站'); refreshMyDocsWindow(); // 刷新当前打开的窗口 const currentWin = findWindowByPath(fullPath); if (currentWin) { currentWin.div.querySelector('[data-action="close"]')?.click(); openFolderByPath(fullPath); } } else { alert('删除失败'); } } } // ====== 辅助函数:获取文件夹的完整路径 ====== function getFolderPath(folder) { function findPath(node, target, path) { if (node.type === 'folder' && node.children) { if (node.children.includes(target)) return path + '/' + node.name; for (let child of node.children) { if (child.type === 'folder') { const res = findPath(child, target, path + '/' + node.name); if (res) return res; } } } return null; } return findPath(fileSystem, folder, '')?.replace(/^\/+/, '') || ''; } function showFileProperties(file) { if (!file) return; let sizeStr = '未知'; if (file.content) sizeStr = (file.content.length / 1024).toFixed(2) + ' KB'; else if (file.dbKey) sizeStr = '二进制文件 (IndexedDB)'; alert(`文件属性\n名称:${file.name}\n类型:${file.type}\n大小:${sizeStr}\n位置:${getParentFolder(file)?.name || '根目录'}`); } function createDesktopShortcutFromMenu(file, folderPath) { // 修复:处理 folderPath 为 undefined 的情况(如在桌面上右键点击快捷方式) if (!folderPath && file.fullPath) { const lastSlash = file.fullPath.lastIndexOf('/'); if (lastSlash !== -1) folderPath = file.fullPath.substring(0, lastSlash); } let shortcutName = prompt('请输入快捷方式名称:', file.name); if (!shortcutName) shortcutName = file.name; let emoji = prompt('请输入图标表情符号(可输入一个emoji,例如📄):', '📄'); if (!emoji) emoji = '📄'; // --- 修复开始:改进路径生成逻辑 --- // 将传入的 folderPath 转换为绝对路径 let absolutePath = folderPath; if (absolutePath && !absolutePath.startsWith('全部设备/')) { // 如果当前路径是相对路径,先尝试判断它是否是 root 下的直接子文件夹 const isRootChild = fileSystem.children.some(c => c.type === 'folder' && c.name === absolutePath); if (isRootChild) { // 处理根目录下的文件夹 if (absolutePath === '系统' || absolutePath === '回收站' || absolutePath === '共享文档' || absolutePath === 'Users') { absolutePath = '全部设备/本地磁盘 (C:)/' + absolutePath; } } else { // 如果既不是绝对路径也不是根级文件夹,则拼接到当前用户根 absolutePath = currentUserRoot ? currentUserRoot + '/' + absolutePath : absolutePath; } } // 再拼接文件名 let defaultPath = absolutePath ? absolutePath + '/' + file.name : file.name; // --- 修复结束 --- // 让用户手动输入或修正路径 let userInput = prompt('请输入快捷方式指向的完整路径(当前默认:' + defaultPath + '):\n您可以在下方修改此路径。', defaultPath); if (userInput === null) { alert('取消创建快捷方式'); return; } let finalPath = userInput.trim(); if (finalPath === '') { alert('路径不能为空,取消创建'); return; } // 更加稳健的路径验证方法 // 将路径拆分为:父文件夹路径 + 文件名 let lastSlashIndex = finalPath.lastIndexOf('/'); let parentPath = finalPath.substring(0, lastSlashIndex); let targetName = finalPath.substring(lastSlashIndex + 1); // 先找到父文件夹 let parentFolder = getFolderByPath(parentPath); if (!parentFolder) { alert('路径无效:找不到父文件夹。请确认路径正确。\n快捷方式创建已取消。'); return; } // 直接在父文件夹里查找目标文件或文件夹 let targetItem = parentFolder.children.find(c => c.name === targetName); if (!targetItem) { alert('路径无效:在父文件夹中找不到指定的文件或文件夹。\n快捷方式创建已取消。'); return; } // 判断目标是文件还是文件夹 const isFolder = targetItem.type === 'folder'; desktopShortcuts.push({ id: generateShortcutId(), name: shortcutName, emoji: emoji, fullPath: finalPath, isFolder: isFolder, isWeb: false }); saveShortcuts(); renderDesktopIcons(); alert('桌面快捷方式已创建!'); } document.addEventListener('touchstart', onTouchStart, { passive: false }); document.addEventListener('touchmove', onTouchMove, { passive: false }); document.addEventListener('touchend', onTouchEnd); document.addEventListener('touchcancel', clearLongPress); // 鼠标事件(电脑端长按) document.addEventListener('mousedown', onMouseDown); document.addEventListener('mousemove', onMouseMove); document.addEventListener('mouseup', onMouseUp); // ====== 新增:全局音频解锁机制 ====== const unlockAudio = () => { const audio = document.getElementById('audioPlayer'); const gameAudio = document.getElementById('gameAudioPlayer'); [audio, gameAudio].forEach(el => { if (el) { el.play().then(() => { el.pause(); el.currentTime = 0; console.log('✅ 音频上下文已解锁'); }).catch(() => {}); } }); // 执行待播放队列 while (pendingSounds.length > 0) { const item = pendingSounds.shift(); item.audio.play().catch(e => console.warn('恢复播放失败:', e)); console.log('✅ 恢复待播放音效'); } document.removeEventListener('click', unlockAudio); document.removeEventListener('touchstart', unlockAudio); }; document.addEventListener('click', unlockAudio); document.addEventListener('touchstart', unlockAudio); // ====== 新增结束 ====== // ====== 新增:任务栏音量控制 ====== function initVolumePanel() { const panel = document.getElementById('volumePanel'); const icon = document.getElementById('volumeIcon'); const closeBtn = document.getElementById('volumeClose'); const slider = document.getElementById('volumeSlider'); const percent = document.getElementById('volumePercent'); const playPauseBtn = document.getElementById('playPauseBtn'); const stopBtn = document.getElementById('stopBtn'); const trackStatus = document.getElementById('trackStatus'); const currentTrack = document.getElementById('currentTrack'); const savedVol = localStorage.getItem('xp_volume_level'); if (savedVol !== null) { const vol = parseInt(savedVol); if (!isNaN(vol) && vol >= 0 && vol <= 100) { slider.value = vol; percent.textContent = vol + '%'; const gameAudio = document.getElementById('gameAudioPlayer'); if (gameAudio) gameAudio.volume = vol / 100; } } icon.addEventListener('click', (e) => { e.stopPropagation(); volumePanelVisible = !volumePanelVisible; panel.style.display = volumePanelVisible ? 'block' : 'none'; if (volumePanelVisible) updatePanelState(); }); closeBtn.addEventListener('click', () => { panel.style.display = 'none'; volumePanelVisible = false; }); document.addEventListener('click', (e) => { if (volumePanelVisible && !panel.contains(e.target) && e.target !== icon) { panel.style.display = 'none'; volumePanelVisible = false; } }); slider.addEventListener('input', () => { const val = parseInt(slider.value); percent.textContent = val + '%'; const gameAudio = document.getElementById('gameAudioPlayer'); if (gameAudio) { gameAudio.volume = val / 100; localStorage.setItem('xp_volume_level', val.toString()); } const audioPlayer = document.getElementById('audioPlayer'); if (audioPlayer) audioPlayer.volume = val / 100; }); playPauseBtn.addEventListener('click', () => { const gameAudio = document.getElementById('gameAudioPlayer'); if (!gameAudio) return; if (gameAudio.paused) { gameAudio.play().catch(e => console.warn('播放失败:', e)); } else { gameAudio.pause(); } updatePanelState(); }); stopBtn.addEventListener('click', () => { const gameAudio = document.getElementById('gameAudioPlayer'); if (gameAudio) { gameAudio.pause(); gameAudio.currentTime = 0; gameAudio.src = ''; currentAudioSrc = null; currentAudioName = '无'; isAudioPlaying = false; updatePanelState(); } }); const gameAudio = document.getElementById('gameAudioPlayer'); if (gameAudio) { gameAudio.addEventListener('play', () => { isAudioPlaying = true; updatePanelState(); }); gameAudio.addEventListener('pause', () => { isAudioPlaying = false; updatePanelState(); }); gameAudio.addEventListener('ended', () => { isAudioPlaying = false; updatePanelState(); }); } function updatePanelState() { const gameAudio = document.getElementById('gameAudioPlayer'); if (!gameAudio) return; const trackEl = document.getElementById('currentTrack'); const statusEl = document.getElementById('trackStatus'); const playPauseBtn = document.getElementById('playPauseBtn'); if (gameAudio.src) { const name = currentAudioName || gameAudio.src.split('/').pop() || '未知曲目'; trackEl.textContent = name; const state = gameAudio.paused ? '已暂停' : '播放中'; statusEl.textContent = state; playPauseBtn.textContent = gameAudio.paused ? '▶️ 播放' : '⏸️ 暂停'; } else { trackEl.textContent = '无'; statusEl.textContent = '空闲'; playPauseBtn.textContent = '▶️ 播放'; } } window._updateVolumePanel = updatePanelState; window._setCurrentTrack = (name) => { currentAudioName = name; updatePanelState(); }; } if (document.readyState === 'complete') { initVolumePanel(); } else { document.addEventListener('DOMContentLoaded', initVolumePanel); } // ====== 新增结束 ====== // ====== 全屏切换 ====== document.getElementById('fullscreen-btn')?.addEventListener('click', function(e) { e.stopPropagation(); if (!document.fullscreenElement) { document.documentElement.requestFullscreen?.().catch(err => console.warn(err)); this.textContent = '⧉'; this.style.color = '#00FF00'; } else { document.exitFullscreen?.().catch(err => console.warn(err)); this.textContent = '⛶'; this.style.color = '#aaa'; } }); document.addEventListener('fullscreenchange', () => { const btn = document.getElementById('fullscreen-btn'); if (!btn) return; if (document.fullscreenElement) { btn.textContent = '⧉'; btn.style.color = '#00FF00'; } else { btn.textContent = '⛶'; btn.style.color = '#aaa'; } }); // ====== 全屏切换结束 ====== // ====== 新增:全新开箱即用体验 (OOBE) ====== let oobeStep = 0; function startOOBE() { // 1. 全屏播放 GIF 和 音频 (修复音乐中断问题) const welcomeDiv = document.createElement('div'); welcomeDiv.id = 'oobe-welcome'; welcomeDiv.style.cssText = ` position: fixed; inset: 0; z-index: 999999; background: #000; display: flex; justify-content: center; align-items: center; overflow: hidden; `; welcomeDiv.innerHTML = ` `; document.body.appendChild(welcomeDiv); // 尝试自动播放(部分浏览器会拦截 autoplay) const oobeAudio = welcomeDiv.querySelector('#oobe-audio'); if (oobeAudio) oobeAudio.play().catch(() => {}); // 点击画面可跳过 GIF welcomeDiv.addEventListener('click', function handler() { welcomeDiv.removeEventListener('click', handler); finishIntro(); }); // 【核心修复】5 秒后自动强制跳转 setTimeout(() => { if (document.body.contains(welcomeDiv)) { finishIntro(); } }, 5500); } // 结束 GIF 播放 (修复:确保背景音乐持续播放) function finishIntro() { const div = document.getElementById('oobe-welcome'); if (div) { // 【核心修复】把音频从容器中"解救"出来,挂载到页面,防止被销毁 const audio = div.querySelector('#oobe-audio'); if (audio) { document.body.appendChild(audio); audio.style.cssText = 'display: none; position: absolute;'; // 隐藏音频界面,让它默默播放 window._oobeAudio = audio; // 全局存储,供后续关闭 } div.remove(); } showOOBEStep1(); } // ====== 第1步:欢迎使用 (修复:垂直居中) ====== function showOOBEStep1() { oobeStep = 1; const overlay = document.createElement('div'); overlay.id = 'oobe-container'; overlay.style.cssText = ` position: fixed; inset: 0; z-index: 999999; background: url('imgs/login-bg.jpeg') center/cover no-repeat; display: flex; flex-direction: column; justify-content: center; align-items: center; `; overlay.innerHTML = `

欢迎使用 Microsoft Windows

感谢您购买 Microsoft Windows XP。

让我们花几分钟来设置您的计算机。

`; document.body.appendChild(overlay); } // ====== 第2步:Hmail 注册 ====== function showOOBEStep2() { const oldOverlay = document.getElementById('oobe-container'); if (oldOverlay) oldOverlay.remove(); oobeStep = 2; const overlay = document.createElement('div'); overlay.id = 'oobe-container'; overlay.style.cssText = ` position: fixed; inset: 0; z-index: 999999; background: url('imgs/login-bg.jpeg') center/cover no-repeat; display: flex; flex-direction: column; justify-content: center; align-items: center; `; overlay.innerHTML = `

现在与 Hmail 注册吗?

联机与 Hmail 注册,我们会通知您感兴趣的新产品、产品更新、事件、促销和特别赠品。由您自己决定是否要注册。

准备好与 Hmail 联机注册了吗?

Hmail 承诺保护个人隐私,不会泄露您的信息。

`; document.body.appendChild(overlay); const radios = overlay.querySelectorAll('input[name="hmail_choice"]'); const iframeArea = overlay.querySelector('#hmail-iframe-area'); const nextBtn = overlay.querySelector('#oobe-step2-next'); radios.forEach(r => { r.addEventListener('change', (e) => { if (e.target.value === 'yes') { iframeArea.style.display = 'block'; nextBtn.style.display = 'inline-block'; } else { iframeArea.style.display = 'none'; nextBtn.style.display = 'inline-block'; } }); }); // 监听 Hmail 注册成功消息 → 自动进入下一步 if (window._oobeHmailListener) { window.removeEventListener('message', window._oobeHmailListener); } window._oobeHmailListener = (e) => { if (e.data === 'hmail_login_success') { window.removeEventListener('message', window._oobeHmailListener); window._oobeHmailListener = null; showOOBEStep3(); } }; window.addEventListener('message', window._oobeHmailListener); } function checkOOBERegister() { const choice = document.querySelector('input[name="hmail_choice"]:checked'); if (choice && choice.value === 'yes') { alert('请在上方 Hmail 窗格中完成注册或登录。\n(若不想注册,请选择"否,现在不注册"并继续。)'); return; } else { showOOBEStep3(); } } // ====== 第3步:创建用户 ====== function showOOBEStep3() { const oldOverlay = document.getElementById('oobe-container'); if (oldOverlay) oldOverlay.remove(); oobeStep = 3; const overlay = document.createElement('div'); overlay.id = 'oobe-container'; overlay.style.cssText = ` position: fixed; inset: 0; z-index: 999999; background: url('imgs/login-bg.jpeg') center/cover no-repeat; display: flex; flex-direction: column; justify-content: center; align-items: center; `; overlay.innerHTML = `

谁会使用这台计算机?

请输入将使用此计算机的每位用户的名字。

`; document.body.appendChild(overlay); } // ====== 第4步:谢谢 ====== function showOOBEStep4() { const oldOverlay = document.getElementById('oobe-container'); if (oldOverlay) oldOverlay.remove(); oobeStep = 4; const overlay = document.createElement('div'); overlay.id = 'oobe-container'; overlay.style.cssText = ` position: fixed; inset: 0; z-index: 999999; background: url('imgs/login-bg.jpeg') center/cover no-repeat; display: flex; flex-direction: column; justify-content: center; align-items: center; `; overlay.innerHTML = `

谢谢!

祝贺您!您现在可以使用了!这是您刚刚完成的:

您的计算机已进行 Internet 访问配置。

要了解 Windows XP 激动人心的新功能,请使用产品漫游。您也可以在帮助和支持中心找到有用的信息。

`; document.body.appendChild(overlay); } // ====== 写入状态并进入登录界面 ====== function completeOOBE() { // 1. 彻底关闭并释放 OOBE 背景音乐 if (window._oobeAudio) { window._oobeAudio.pause(); window._oobeAudio.currentTime = 0; window._oobeAudio.remove(); window._oobeAudio = null; } // 2. 读取第3步填写的用户名(先读取,再移除容器,避免元素被销毁后取值报错) const user1 = (document.getElementById('oobe-user1')?.value || '').trim() || '管理员'; const user2 = (document.getElementById('oobe-user2')?.value || '').trim(); const user3 = (document.getElementById('oobe-user3')?.value || '').trim(); const user4 = (document.getElementById('oobe-user4')?.value || '').trim(); const user5 = (document.getElementById('oobe-user5')?.value || '').trim(); const container = document.getElementById('oobe-container'); if (container) container.remove(); localStorage.setItem('xp_oobe_done', 'true'); // 3. 写入用户账户 if (users.admin) users.admin.name = user1; const addUserIfNotExists = (name) => { if (!name) return; const existing = Object.values(users).find(u => u.name === name); if (!existing) { const newId = 'user_' + Date.now() + Math.random(); users[newId] = { id: newId, name: name, avatar: '👤', isAdmin: false, wallpaper: '', files: JSON.parse(JSON.stringify(fileSystem)), shortcuts: [], password: '' }; } }; addUserIfNotExists(user2); addUserIfNotExists(user3); addUserIfNotExists(user4); addUserIfNotExists(user5); saveUsers(); // 4. 进入登录页 showLoginScreen(); } // ====== 暴露到 window,供内联 onclick 调用 ====== window.startOOBE = startOOBE; window.showOOBEStep1 = showOOBEStep1; window.showOOBEStep2 = showOOBEStep2; window.checkOOBERegister = checkOOBERegister; window.showOOBEStep3 = showOOBEStep3; window.showOOBEStep4 = showOOBEStep4; window.completeOOBE = completeOOBE; // ====== OOBE 结束 ====== })(); webto.work