# WinWeb **Repository Path**: zhangmf9773/WinWeb ## Basic Information - **Project Name**: WinWeb - **Description**: Web OS - Windows-like desktop in browser with Fluent Design - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-06-23 - **Last Updated**: 2026-06-23 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 🪟 WinWeb OS > 运行在浏览器中的轻量级 Web 桌面操作系统 · Fluent Design System [![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) [![Go](https://img.shields.io/badge/Go-1.22+-00ADD8?logo=go)](https://go.dev/) [![React](https://img.shields.io/badge/React-18-61DAFB?logo=react)](https://react.dev/) [![TypeScript](https://img.shields.io/badge/TypeScript-5.7-3178C6?logo=typescript)](https://www.typescriptlang.org/) [![Vite](https://img.shields.io/badge/Vite-6-646CFF?logo=vite)](https://vite.dev/) **WinWeb OS** 是一个完全运行在浏览器中的桌面操作系统模拟器,视觉风格基于 **Fluent Design System**,还原 Windows 经典交互体验。整个系统包含完整的桌面环境、窗口管理器、文件系统和内置应用,后端提供数据持久化与文件存储服务。 --- ## ✨ 功能特性 ### 🖥️ 桌面环境 | 组件 | 说明 | |-------------|---------------------------------------------------| | **桌面图标** | 单击选中(蓝色高亮 + 阴影)、双击打开、F2 重命名、右键菜单 | | **图标网格布局** | 自动排列,支持自由拖拽放置,位置持久化到服务端 | | **开始菜单** | 居中弹出式面板(560px 宽),实时搜索过滤、应用快捷方式网格、关机/重启 | | **任务栏** | 48px 高度玻璃态底栏:居中开始按钮 + 应用窗口按钮(图标+标题)、点击最小化/恢复、右键关闭 | | **系统托盘** | 右侧实时时钟(HH:MM 格式)、小组件面板开关 | | **右键上下文菜单** | 全局右键菜单系统,支持子菜单嵌套、分隔线、危险操作红色高亮、disabled 状态 | ### 🪟 窗口管理 | 功能 | 实现细节 | |-----------------|------------------------------------------| | **多窗口** | 同时运行多个应用,每个独立窗口,z-index 自增层级管理 | | **拖拽移动** | 标题栏拖拽,拖到屏幕顶部自动最大化,拖到左/右边缘半屏分屏 | | **8 向调整大小** | 四条边 + 四个角,通过 `react-rnd` 实现像素级精确调整 | | **吸附预览** | 拖拽至边缘时显示蓝色半透明虚线区域指示最终位置 | | **最大化/还原** | 最大化时精确记录原始位置和尺寸,还原时完整恢复;最大化窗口任务栏不遮挡 | | **最小化** | 窗口隐藏至任务栏,点击任务栏按钮恢复并自动聚焦 | | **层叠 / 平铺** | 桌面右键菜单一键层叠(阶梯排列,30px 递进)或自动网格平铺(√n 行列布局) | | **Alt+Tab 切换器** | 全屏覆盖层,显示所有窗口图标+标题,Tab 键正向循环,Shift+Tab 反向 | ### 📂 文件系统 | 功能 | 说明 | |-------------|--------------------------------------------------------------------------------------| | **文件资源管理器** | 列表/网格双视图、面包屑导航(路径可点击跳转)、粘性表头 | | **新建文件夹** | 右键或工具栏创建,即时刷新 | | **重命名** | 选中后 F2 或右键重命名(前端限制:未完成) | | **删除** | 选中后 Delete 或右键删除 | | **路径安全** | Go 服务端 `filepath.Clean` + `strings.HasPrefix` 双层路径穿越防护 | | **用户隔离** | 每个用户独立目录 `data/home/{userID}/`,预创建 Desktop/Documents/Downloads/Pictures/Music/Videos | | **文件上传** | 支持 multipart 上传,50MB 限制 | | **文件预览** | 文本文件双击在记事本打开,图片等二进制文件根据扩展名返回正确 Content-Type | ### 📝 内置应用 | 应用 | 功能 | |----------------|-------------------------------------------------| | **📂 文件资源管理器** | 完整文件浏览管理,面包屑导航,列表/网格切换 | | **📝 记事本** | 多窗口独立编辑,Ctrl+S 保存、Ctrl+O 打开、Ctrl+N 新建,底部状态栏显示行数 | | **⚙️ 设置** | 壁纸切换(内置 6 张)、账户信息、关于页面 | ### 🎨 设计系统(Fluent Design) | 元素 | 实现 | |------------|--------------------------------------------------------------------------------| | **玻璃拟态** | `backdrop-filter: saturate(180%) blur(30px)` | | **亚克力效果** | 半透明背景 + 1px 半透明边框 + 内发光 | | **暗色主题** | 全局深色配色(`#0a0e1a` 桌面背景 → `#1e2030` 窗口表面),降低视觉疲劳 | | **弹性动画** | `cubic-bezier(0.34, 1.56, 0.64, 1)` 弹簧缓动用于开始菜单弹出;窗口打开 `scale(0.92) → scale(1)` | | **字体栈** | Segoe UI / Microsoft YaHei / PingFang SC / system-ui | | **自定义滚动条** | 6px 宽 Fluent 风格半透明滚动条 | ### 🔐 安全 | 层级 | 措施 | |--------------|-------------------------------------------------------| | **认证** | JWT(HS256)签发,支持 Authorization Bearer 头和 Cookie 双通道 | | **密码** | bcrypt 哈希存储,注册时自动创建用户家目录 | | **HTTP 安全头** | CSP / HSTS / X-Content-Type-Options / X-Frame-Options | | **CSRF** | SameSite Cookie | | **文件隔离** | 用户 ID 目录隔离 + 路径穿越防护 | | **速率限制** | 10 req/s per IP(令牌桶算法) | | **上传限制** | multipart 50MB 硬限制 | ### 💾 会话持久化 | 层 | 机制 | |------------------|------------------------------------------------------------------------------------| | **内存** | Zustand(即时读写,驱动 UI) | | **localStorage** | Zustand persist 中间件,浏览器关闭后恢复(桌面图标位置、窗口状态、壁纸) | | **服务端** | `PUT /api/session` 将完整桌面状态(windows、icons、iconPositions、wallpaper)JSON 序列化存入 SQLite | --- ## 🏗️ 架构 ``` ┌────────────────────────────────────────────────────────┐ │ 浏览器 (:3000) │ │ ┌──────────────────────────────────────────────────┐ │ │ │ React 18 + TypeScript │ │ │ │ │ │ │ │ App.tsx │ │ │ │ ├─ LoginScreen (未认证 → 毛玻璃登录卡片) │ │ │ │ └─ DesktopEnvironment (已认证 → 完整桌面) │ │ │ │ ├─ Desktop 壁纸 + 图标网格 │ │ │ │ ├─ WindowManager 窗口调度 (FileExplorer │ │ │ │ │ / Notepad / Settings) │ │ │ │ ├─ WindowFrame Rnd 拖拽框架 + 吸附 │ │ │ │ ├─ Taskbar 48px 底栏 │ │ │ │ ├─ StartMenu 居中弹出 + 搜索 │ │ │ │ ├─ AltTabSwitcher 全屏窗口切换覆盖层 │ │ │ │ ├─ WidgetPanel 左侧滑入小组件 │ │ │ │ ├─ ContextMenu 全局右键菜单 │ │ │ │ └─ ShutdownDialog 关机确认 │ │ │ │ │ │ │ │ Zustand Store (sessionStore) │ │ │ │ ├─ windows[] 窗口状态数组 │ │ │ │ ├─ desktopIcons[] 桌面图标 │ │ │ │ ├─ iconPositions{} 图标位置 │ │ │ │ ├─ wallpaper 壁纸 URL │ │ │ │ ├─ activeWindowId 当前活跃窗口 │ │ │ │ ├─ nextZIndex 自增层级计数器 │ │ │ │ ├─ preMaximizeMap{} 最大化前位置记忆 │ │ │ │ └─ 20+ actions 完整窗口操作 API │ │ │ │ │ │ │ │ Hooks: useSessionSync / useKeyboard / │ │ │ │ useClickOutside / useDoubleClick │ │ │ └──────────────────┬───────────────────────────────┘ │ │ │ REST API (/api/*) │ │ │ Vite proxy → :8080 │ └─────────────────────┼──────────────────────────────────┘ │ ┌─────────────────────┼──────────────────────────────────┐ │ Go API Server (:8080) │ │ │ │ Middleware Pipeline (顺序): │ │ CORS → SecurityHeaders → RateLimit → Auth │ │ │ │ Public: POST /api/auth/register, /login │ │ │ │ Protected (JWT required): │ │ ├─ GET /api/session 获取桌面状态 │ │ ├─ PUT /api/session 保存桌面状态 │ │ ├─ GET /api/apps 获取应用列表 │ │ ├─ GET /api/files/list 列出目录 │ │ ├─ GET /api/files/read 读取文件内容 │ │ ├─ POST /api/files/write 写入文件 │ │ ├─ POST /api/files/mkdir 创建目录 │ │ ├─ DELETE /api/files/delete 删除文件/目录 │ │ ├─ POST /api/files/rename 重命名 │ │ ├─ POST /api/files/upload 上传文件 │ │ └─ GET /* SPA fallback → index.html │ │ │ │ Layer Layout: │ │ handler/ → service/ → store/ (SQLite WAL) │ │ │ │ Data: │ │ ├─ data/winweb.db SQLite (users, sessions) │ │ └─ data/home/{userID}/ 用户文件隔离目录 │ │ ├─ Desktop/ │ │ ├─ Documents/ │ │ ├─ Downloads/ │ │ ├─ Pictures/ │ │ ├─ Music/ │ │ └─ Videos/ │ └─────────────────────────────────────────────────────────┘ ``` --- ## 📁 项目结构 ``` WinWeb/ ├── start.sh # 一键启动脚本(编译 Go → 启动后端 → 启动 Vite) ├── Dockerfile # 多阶段构建(Go 编译 + 静态文件 → 单二进制) ├── docker-compose.yml ├── README.md │ ├── server/ # Go 后端 │ ├── main.go # 入口:路由注册 + 中间件链 + 静态文件服务 │ ├── go.mod │ └── internal/ │ ├── middleware/ │ │ ├── auth.go # JWT Bearer/Cookie 双通道认证,token 签发 │ │ ├── cors.go # CORS 配置 │ │ ├── security.go # CSP/HSTS/X-Content-Type/X-Frame │ │ └── ratelimit.go # 令牌桶 IP 速率限制 │ ├── handler/ │ │ ├── auth.go # 注册(bcrypt + 建家目录)/ 登录(JWT 签发) │ │ ├── files.go # 文件 CRUD + 上传 + Content-Type 映射 │ │ ├── session.go # 桌面状态存取 │ │ └── apps.go # 应用列表 │ ├── service/ │ │ ├── auth.go # bcrypt 哈希 + 用户创建 │ │ ├── files.go # 路径解析 + 穿越防护 + 文件操作 + 家目录初始化 │ │ └── session.go # JSON 序列化/反序列化 │ ├── store/ │ │ ├── db.go # SQLite 初始化 (WAL 模式 + 自动建表) │ │ ├── user.go # 用户 CRUD │ │ └── session.go # 会话存取 │ └── model/ │ ├── user.go # User 结构体 │ ├── session.go # SessionState 结构体 │ └── file.go # FileInfo 结构体 │ └── frontend/ # React 前端 ├── package.json ├── vite.config.ts # Vite 配置 + /api → :8080 代理 ├── tsconfig.json └── src/ ├── main.tsx # ReactDOM 入口 ├── App.tsx # 根组件:登录屏 / 桌面环境 ├── api/ # API 客户端 │ ├── client.ts # fetch 封装(Base URL + JSON 解析 + token 管理) │ ├── auth.ts # login/register API │ ├── files.ts # 文件 CRUD API │ └── session.ts # 会话存取 API ├── stores/ # Zustand 状态管理 │ ├── authStore.ts # 认证状态(token、user、loading、error) │ └── sessionStore.ts # 桌面完整状态 + 20+ actions(Zustand persist → localStorage) ├── hooks/ # 自定义 Hooks │ ├── useSessionSync.ts # 三层持久化同步(localStorage ↔ 服务端) │ ├── useKeyboard.ts # 全局快捷键(Win/E → 资源管理器,Win → 开始菜单,Esc) │ ├── useClickOutside.ts # 点击外部关闭(菜单、面板) │ └── useDoubleClick.ts # 单击/双击区分(300ms 窗口) ├── shell/ # 桌面 Shell 组件 │ ├── Desktop.tsx # 桌面壁纸 + 图标网格 + 壁纸切换 │ ├── DesktopIcon.tsx # 单个桌面图标(选中态、拖拽、双击、右键) │ ├── IconGrid.tsx # 图标网格布局(自动换行) │ ├── WindowManager.tsx # 窗口应用路由(appId → 组件映射) │ ├── WindowFrame.tsx # Rnd 拖拽框架 + 8向调整 + 吸附预览 + 标题栏右键 │ ├── Taskbar.tsx # 任务栏(开始按钮 + 窗口按钮 + 系统托盘) │ ├── StartMenu.tsx # 开始菜单(搜索框 + 应用网格 + 关机按钮) │ ├── SystemTray.tsx # 系统托盘(时钟 + 小组件开关) │ ├── ContextMenu.tsx # 全局右键菜单系统(嵌套子菜单 + 危险操作) │ ├── AltTabSwitcher.tsx # Alt+Tab 窗口切换覆盖层 │ ├── WidgetPanel.tsx # 左侧滑入小组件面板 │ ├── ShutdownDialog.tsx # 关机确认模态框 │ └── snap.ts # 窗口吸附计算(全屏/半屏左/半屏右) ├── apps/ # 内置应用 │ ├── FileExplorer/ # 文件资源管理器(列表/网格视图 + 面包屑) │ ├── Notepad/ # 记事本(Ctrl+S/O/N + 行数统计) │ └── Settings/ # 设置(壁纸 + 账户 + 关于) └── styles/ # 样式系统 ├── theme.css # Fluent Design Token (CSS 变量 + 动画 + 组件样式) └── window.css # 窗口框架专有样式 ``` --- ## 🚀 快速开始 ### 前置要求 - **Go** ≥ 1.22 - **Node.js** ≥ 18 ### 一键启动 ```bash git clone https://gitee.com/zhangmf9773/WinWeb.git cd WinWeb chmod +x start.sh ./start.sh ``` 脚本自动完成:编译 Go 后端 → 启动 API Server (:8080) → 启动 Vite Dev Server (:3000) 浏览器打开 `http://localhost:3000`,注册账户即可使用。 ### 手动启动 **终端 1 — 启动后端:** ```bash cd server go run main.go # 🚀 WinWeb Server running on http://localhost:8080 ``` **终端 2 — 启动前端:** ```bash cd frontend npm install npm run dev # ➜ Local: http://localhost:3000 ``` `vite.config.ts` 已将 `/api` 请求代理到 `http://localhost:8080`。 ### 生产构建 ```bash # 构建前端 cd frontend && npm run build # 将 dist 复制到 server/static cp -r dist ../server/static # 编译并启动 cd ../server go build -o winweb-server . ./winweb-server # 访问 http://localhost:8080(前后端合一,单端口) ``` ### Docker 部署 ```bash docker compose up -d # 访问 http://localhost:8080 ``` `Dockerfile` 使用多阶段构建:第一阶段编译 Go 二进制、第二阶段构建前端、最终合成最小镜像。 --- ## 📡 API 文档 ### 认证 | 方法 | 路径 | 说明 | 请求体 | 响应 | |-------|----------------------|-------|------------------------|-----------------| | POST | `/api/auth/register` | 注册 | `{username, password}` | `{token, user}` | | POST | `/api/auth/login` | 登录 | `{username, password}` | `{token, user}` | 注册时自动创建用户家目录(Desktop/Documents/Downloads/Pictures/Music/Videos)。 ### 会话 | 方法 | 路径 | 说明 | 请求/响应 | |-------|----------------|--------|--------------------------------------------------------| | GET | `/api/session` | 获取桌面状态 | 返回 `{windows, desktopIcons, iconPositions, wallpaper}` | | PUT | `/api/session` | 保存桌面状态 | 请求体同 GET 响应结构 | ### 应用 | 方法 | 路径 | 说明 | |-------|-------------|------------------------------------| | GET | `/api/apps` | 返回内置应用列表 `[{id, name, icon, ...}]` | ### 文件 | 方法 | 路径 | 参数/请求体 | 说明 | |--------|---------------------|--------------------------|-------------------------------------| | GET | `/api/files/list` | `?path=/` | 列出目录,返回 `{files: FileInfo[], path}` | | GET | `/api/files/read` | `?path=/file` | 读取文件,返回 `{path, content}` | | POST | `/api/files/write` | `{path, content}` | 写入/覆盖文件,自动创建父目录 | | POST | `/api/files/mkdir` | `{path}` | 创建目录(含父目录) | | DELETE | `/api/files/delete` | `{path}` | 删除文件或目录 | | POST | `/api/files/rename` | `{oldPath, newPath}` | 重命名/移动 | | POST | `/api/files/upload` | `multipart: file + path` | 上传文件(最大 50MB) | 所有文件 API 均享受用户目录隔离 + 路径穿越防护。 --- ## 🛠️ 技术栈与设计决策 | 层 | 选择 | 理由 | |--------------|---------------------------------|-------------------------------------| | **前端框架** | React 18 + TypeScript | 类型安全,组件化,生态丰富 | | **构建工具** | Vite 6 | 极速 HMR(< 100ms),原生 ESM | | **状态管理** | Zustand | 2KB 体积,无 Provider 嵌套,内置 persist 中间件 | | **窗口拖拽** | react-rnd | 8 向调整大小 + CSS transform 拖拽 | | **HTTP 客户端** | 原生 fetch | 零依赖封装,50 行完成 token 管理 + JSON 解析 | | **图标** | Emoji + Unicode | 跨平台一致渲染,零网络请求 | | **后端语言** | Go 1.22 | 标准库 net/http 路由增强(方法匹配),低内存、高并发 | | **数据库** | SQLite (WAL 模式) | 单文件、零配置,WAL 支持并发读 | | **认证** | JWT (HS256) + bcrypt | 无状态认证,Bearer/Cookie 双通道 | | **CSS 架构** | CSS Variables + Utility Classes | 无运行时开销,主题变量集中管理 | ### 设计原则 - **零学习成本** — 完全复刻 Windows 交互习惯,凭肌肉记忆即可使用 - **单人可维护** — 核心代码约 7500 行,分层清晰(handler → service → store) - **极致轻量** — Go 二进制 ~12MB,前端 gzip ~88KB,空闲内存 < 30MB - **安全第一** — 纵深防御:TLS → CSP → 输入验证 → 文件隔离 → 速率限制 --- ## 🎮 快捷键 | 按键 | 功能 | |--------------------|-------------------| | `Win` / `Ctrl+Esc` | 打开/关闭开始菜单 | | `Win+E` | 打开文件资源管理器 | | `Alt+Tab` | 窗口切换器(正向循环) | | `Alt+Shift+Tab` | 窗口切换器(反向循环) | | `Esc` | 关闭开始菜单 / 右键菜单 | | `Ctrl+S` | 记事本保存 | | `Ctrl+O` | 记事本打开 | | `Ctrl+N` | 记事本新建 | | `F2` | 桌面图标重命名(前端预留,待完成) | | `Delete` | 文件资源管理器中删除选中文件 | --- ## 📝 License MIT License --- **Made with ❤️ by WinWeb OS Team** 🤖 Generated with [Claude Code](https://claude.com/claude-code)