﻿# NyouOS-On-Web 2.0 开发者指南

[简体中文](DEVELOPER_GUIDE.md) | [English](DEVELOPER_GUIDE_EN.md)

本文面向需要理解、调试或扩展 NyouOS-On-Web 的开发者。当前代码是传统浏览器脚本架构：没有 npm 运行时依赖、ES Module、构建产物或前端框架，模块通过  按顺序加载并把对象放到全局作用域。

使用说明见[项目 README](../README.md)，视觉和组件细节见 [NyouOS UI 指南](fluent-ui-guide.md)。

## 1. 运行与开发基线

在仓库根目录启动静态服务器：



打开 <http://localhost:8000/>，并使用浏览器开发者工具调试。不要以  作为开发基线：资源预载、远程请求、摄像头、剪贴板和文件选择器会表现不同。

项目当前没有自动化测试或 lint 配置。提交前至少执行 JavaScript 语法检查并进行浏览器冒烟测试：



## 2. 架构总览



### 目录职责

| 目录 | 职责 |
| --- | --- |
|  | 存储、全局状态、国际化、文件导入、收藏、FluentUI/FluentWindow、SurfAi、灵翼和资源清单 |
|  | 系统级屏幕与外壳：启动、OOBE、桌面、任务栏、开始菜单、控制/通知中心、任务视图、窗口和小组件 |
|  | 原生应用组件；每个应用由  挂载到窗口内容区 |
|  | iframe Web/PWA 注册器与应用目录 |
|  | 基础令牌、系统外壳、组件、应用共享样式及各大型界面样式 |
|  | 图标、壁纸、头像、预载资源和插图 |

### 脚本加载顺序

全局对象有真实的先后依赖。例如  依赖 ，应用依赖 、、 和 ， 则负责把所有对象初始化起来。因此：

- 新核心脚本应放在首个使用它的脚本之前。
- 新原生应用脚本应在  之后、 之前加载。
-  必须尽可能早加载，才能在其他资源执行前恢复严格 CSP。
- 不要使用 、 或随意重排脚本，除非同时消除对应的全局依赖。

## 3. 启动与视图生命周期

 的主要值为 、、 和 。 监听  并切换对应屏幕。

首次访问时，OOBE 根据自己的持久化标记决定是否显示；完成后进入系统流程。正常启动由  预载资源并进入锁屏。锁屏交互进入登录页，PIN 校验成功后进入桌面。



这些 API 操作的是 Web UI 状态，不会控制宿主计算机。

## 4. Storage 与 State

### Storage

 是  的 JSON 包装器：



核心键：



 清空当前源的全部 ，不只删除上述核心键。不要在普通业务流程调用它。

虚拟文件系统会过滤过大的 Data URL：图片约超过 128 KiB、其他内联数据约超过 2 MiB 时可能移除内容并标记节点。照片和媒体等大对象应写入 IndexedDB/Blob 存储，而不是继续塞入 。

### State

 是运行时唯一状态源，初始化时从  恢复数据：



更新设置时必须调用 ，不要只改对象字段；该方法会保存数据、应用主题/材质等副作用并发出事件。



常用设置包括：

| 字段 | 说明 |
| --- | --- |
|  | 、 或现有界面支持的自动策略 |
|  | 当前实现使用  /  |
| ,  | 桌面与锁屏壁纸 URL/Data URL |
| ,  | 系统材质与窗口模糊 |
| ,  | 材质类型和模糊强度 |
| ,  | 动效和按钮光效 |
| ,  | 手动强调色和壁纸自动取色 |
|  |  应用切换器 |
| ,  | 窗口贴靠能力 |
| ,  | 后台窗口冻结策略 |
|  | 开始菜单固定应用 ID 列表 |
|  | 是否允许外部文件导入虚拟文件系统 |
|  | 运行时严格 CSP |

### 事件总线



常见系统事件有 、、、、、、、、、、 和 。

为长期存在或会重复初始化的组件提供稳定 ，并在关闭时退订，避免监听器叠加。

### 虚拟文件系统

标准根目录包含 、、、 和 。使用状态 API 查找和提交修改：



如果直接修改 ，仍应调用  完成持久化和通知。文件 ID 必须全局唯一；删除到回收站时保留 ，以便恢复。

## 5. 国际化

翻译表位于 ，当前语言键为  和 ：



新增用户可见文本时：

1. 在中英文翻译表加入相同键。
2. 渲染时调用 ，不要缓存语言相关字符串。
3. 应用监听  并重新渲染或更新文本。
4.  优先使用 ，窗口标题会自动更新。

缺失翻译会回退到中文，仍缺失时直接显示键名。

## 6. 窗口管理

 负责窗口创建、聚焦、最小化、最大化、调整尺寸、贴靠、任务栏同步、位置记忆及后台冻结。一个应用 ID 默认只保留一个窗口。



应用配置位于 ：



原生组件可实现以下生命周期钩子：

| 方法 | 调用时机 |
| --- | --- |
|  | 首次创建窗口后；内容容器 ID 为  |
|  |  时优先调用 |
|  | 传入其他打开参数时调用 |
|  | 关闭前调用；返回  取消，或返回解析为布尔值的 Promise |
|  | 后台冻结时暂停计时器、媒体或网络工作 |
|  | 窗口恢复时继续工作并刷新过期内容 |

不会取消关闭的应用可在  中解绑全局事件、断开 、停止媒体流并销毁  实例。若应用可能返回 ，则应先完成确认，只在确定关闭后执行这些清理。

## 7. 新增原生应用

### 7.1 创建组件

在  中定义全局组件：



应用对象是单例；不要假设同一组件存在多个并行实例。

### 7.2 注册与加载

1. 在  添加配置。
2. 在  添加可用应用元数据。
3. 需要默认固定时，将 ID 加入设置默认值 ，并按需要更新任务栏/应用商店逻辑。
4. 在  的应用脚本区域引入 。
5. 添加应用图标、翻译键及必要样式。

不要只修改桌面图标列表：窗口配置缺失时  会拒绝启动。

### 7.3 使用应用内部导航框架

复杂应用优先使用 ：



实例公开 、、、、滚动位置方法和侧栏搜索方法。完整示例见 [NyouOS UI 指南](fluent-ui-guide.md#fluentwindow-应用框架)。

## 8. 小组件

定义集中在 ，布局和交互由  管理。 按应用分组，每个 variant 描述尺寸、主题和渲染器：



异步数据使用已有 / 做 TTL 缓存，并通过  提供加载与失败状态。渲染器创建的 interval、observer 或监听器必须随 DOM 移除而停止。

## 9. 第三方 Web/PWA 应用

 把 URL 包装成窗口组件：



目录项维护在 。注册后还需通过 App Shop 安装流程加入窗口、桌面和固定列表。

限制必须在产品设计中明确：跨域 iframe 的 DOM 不可读取；站点可能拒绝嵌入；登录 Cookie、弹窗、下载、媒体自动播放和权限均受浏览器策略控制。后台冻结会向 iframe 发送：



可控的 Web 应用可监听该消息暂停/恢复耗时任务。

## 10. 网络、权限与安全

- 所有远程数据都应有加载、失败、超时或本地回退状态。
- 将第三方返回文本写入  前必须转义；优先用 。
- URL 必须验证协议，外部窗口使用 。
- 摄像头流关闭时逐轨调用 ；定位和剪贴板失败时给出可理解提示。
- 不把 API Key 写入代码、日志、虚拟文件系统或普通  字段。
- 严格 CSP 在  中定义。新增远程源时先判断是否必要，再同步策略和无网络回退。
-  和客户端加密不能抵御同源恶意脚本；它们只是持久化手段，不是可信密钥库。

## 11. 调试接口



全局通知有两套用途：



 是通知中心的便捷包装。

## 12. 提交前检查

- JavaScript 文件均通过 。
- 从清空站点数据开始完成 OOBE、锁屏、登录和桌面流程。
- 浅色/深色主题、不同强调色和关闭动画/模糊时均可用。
- 应用可打开、最小化、最大化、贴靠、关闭并再次打开。
- 窗口缩到最小尺寸时没有关键控件溢出。
- 中文和英文切换后，窗口标题、导航和动态内容同步更新。
- 刷新后设置、文件、窗口位置和应用数据按预期恢复。
- 无网络、拒绝摄像头/定位权限和 iframe 被拦截时不崩溃。
- 控制台没有新增的未处理异常、重复监听或持续计时器。


