diff --git a/website/css/docs.css b/website/css/docs.css
new file mode 100644
index 0000000..1d6501a
--- /dev/null
+++ b/website/css/docs.css
@@ -0,0 +1,288 @@
+/* ===== 文档页面 ===== */
+.page-docs {
+ position: fixed;
+ inset: 0;
+ display: flex;
+ flex-direction: column;
+ background: var(--bg);
+ overflow: hidden;
+}
+
+/* 顶部栏 */
+.docs-header {
+ height: 56px;
+ flex-shrink: 0;
+ display: flex;
+ align-items: center;
+ gap: 16px;
+ padding: 0 24px;
+ background: rgba(3, 7, 18, 0.95);
+ border-bottom: 1px solid var(--border);
+ backdrop-filter: blur(12px);
+ z-index: 100;
+}
+
+.docs-header-title {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ font-size: 16px;
+ font-weight: 700;
+ color: #fff;
+}
+
+.docs-header-title svg {
+ color: var(--cyan);
+}
+
+.docs-header-breadcrumb {
+ flex: 1;
+ font-size: 14px;
+ color: var(--text-muted);
+}
+
+.docs-header-actions {
+ display: flex;
+ align-items: center;
+ gap: 12px;
+}
+
+.docs-wiki-link {
+ display: flex;
+ align-items: center;
+ gap: 6px;
+ padding: 6px 14px;
+ border: 1px solid var(--border);
+ border-radius: 8px;
+ background: transparent;
+ color: var(--text-secondary);
+ font-size: 13px;
+ text-decoration: none;
+ transition: all 0.2s;
+}
+
+.docs-wiki-link:hover {
+ border-color: var(--border-hover);
+ color: var(--cyan-light);
+ background: rgba(6, 182, 212, 0.05);
+}
+
+/* 布局 */
+.docs-layout {
+ flex: 1;
+ display: flex;
+ overflow: hidden;
+}
+
+/* 左侧导航 */
+.docs-sidebar {
+ width: 260px;
+ flex-shrink: 0;
+ background: rgba(2, 5, 16, 0.6);
+ border-right: 1px solid var(--border);
+ overflow-y: auto;
+ padding: 20px 0;
+}
+
+.docs-nav-section {
+ margin-bottom: 24px;
+}
+
+.docs-nav-section-title {
+ padding: 8px 24px;
+ font-size: 11px;
+ font-weight: 600;
+ text-transform: uppercase;
+ color: var(--text-muted);
+ letter-spacing: 1px;
+}
+
+.docs-nav-item {
+ display: block;
+ padding: 8px 24px 8px 32px;
+ color: var(--text-secondary);
+ text-decoration: none;
+ font-size: 14px;
+ border-left: 3px solid transparent;
+ transition: all 0.15s;
+}
+
+.docs-nav-item:hover {
+ background: rgba(255, 255, 255, 0.03);
+ color: #fff;
+}
+
+.docs-nav-item.active {
+ border-left-color: var(--cyan);
+ color: var(--cyan-light);
+ background: rgba(6, 182, 212, 0.05);
+}
+
+.docs-nav-item .nav-path {
+ display: block;
+ font-size: 11px;
+ color: var(--text-muted);
+ margin-top: 2px;
+ font-family: 'JetBrains Mono', monospace;
+}
+
+/* 左下角固定按钮 */
+.docs-wiki-btn {
+ position: fixed;
+ bottom: 24px;
+ left: 24px;
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ padding: 12px 20px;
+ background: linear-gradient(135deg, var(--cyan), var(--blue));
+ border: none;
+ border-radius: 12px;
+ color: #fff;
+ font-size: 14px;
+ font-weight: 600;
+ text-decoration: none;
+ z-index: 200;
+ box-shadow: 0 4px 20px rgba(6, 182, 212, 0.3);
+ transition: all 0.2s;
+}
+
+.docs-wiki-btn:hover {
+ transform: translateY(-2px);
+ box-shadow: 0 8px 30px rgba(6, 182, 212, 0.4);
+}
+
+.docs-wiki-btn svg {
+ width: 16px;
+ height: 16px;
+}
+
+/* 右侧内容区 */
+.docs-content-wrapper {
+ flex: 1;
+ overflow-y: auto;
+}
+
+.docs-content {
+ max-width: 860px;
+ margin: 0 auto;
+ padding: 40px 48px 100px;
+}
+
+.docs-content h1 {
+ font-size: 32px;
+ font-weight: 800;
+ color: #fff;
+ margin-bottom: 8px;
+ margin-top: 0;
+}
+
+.docs-content h2 {
+ font-size: 22px;
+ font-weight: 700;
+ color: #fff;
+ margin-top: 32px;
+ margin-bottom: 12px;
+ padding-bottom: 8px;
+ border-bottom: 1px solid var(--border);
+}
+
+.docs-content h3 {
+ font-size: 18px;
+ font-weight: 600;
+ color: var(--cyan-light);
+ margin-top: 24px;
+ margin-bottom: 8px;
+}
+
+.docs-content p {
+ font-size: 15px;
+ color: var(--text-secondary);
+ line-height: 1.8;
+ margin-bottom: 12px;
+}
+
+.docs-content strong { color: #fff; }
+
+.docs-content code {
+ font-family: 'JetBrains Mono', monospace;
+ font-size: 13px;
+ background: rgba(6, 182, 212, 0.1);
+ padding: 2px 8px;
+ border-radius: 4px;
+ color: var(--cyan-light);
+}
+
+.docs-content pre {
+ margin: 16px 0;
+ padding: 16px 20px;
+ background: rgba(10, 15, 30, 0.8);
+ border: 1px solid var(--border);
+ border-radius: 10px;
+ overflow-x: auto;
+}
+
+.docs-content pre code {
+ background: transparent;
+ padding: 0;
+ color: #e5e7eb;
+ font-size: 13px;
+ line-height: 1.7;
+}
+
+.docs-content blockquote {
+ margin: 16px 0;
+ padding: 12px 20px;
+ border-left: 4px solid var(--cyan);
+ background: rgba(6, 182, 212, 0.05);
+ border-radius: 0 8px 8px 0;
+}
+
+.docs-content blockquote p { margin-bottom: 0; }
+
+.docs-content ul, .docs-content ol {
+ margin: 12px 0;
+ padding-left: 24px;
+ color: var(--text-secondary);
+}
+
+.docs-content li {
+ margin-bottom: 6px;
+ font-size: 15px;
+ line-height: 1.6;
+}
+
+.docs-content hr {
+ border: none;
+ height: 1px;
+ background: var(--border);
+ margin: 24px 0;
+}
+
+.docs-content table {
+ width: 100%;
+ border-collapse: collapse;
+ margin: 16px 0;
+ font-size: 14px;
+}
+
+.docs-content th {
+ padding: 10px 16px;
+ text-align: left;
+ background: rgba(6, 182, 212, 0.05);
+ border-bottom: 2px solid rgba(6, 182, 212, 0.2);
+ color: #fff;
+ font-weight: 600;
+}
+
+.docs-content td {
+ padding: 10px 16px;
+ border-bottom: 1px solid var(--border);
+ color: var(--text-secondary);
+}
+
+@media (max-width: 768px) {
+ .docs-sidebar { display: none; }
+ .docs-content { padding: 24px 20px 100px; }
+ .docs-wiki-btn span { display: none; }
+}
diff --git a/website/css/hero.css b/website/css/hero.css
index e15003e..2bab651 100644
--- a/website/css/hero.css
+++ b/website/css/hero.css
@@ -193,24 +193,100 @@
}
}
-.hero-logo {
+/* ===== 3D 交互立方体 ===== */
+.cube-scene {
position: relative;
+ width: 200px;
+ height: 200px;
+ perspective: 800px;
z-index: 1;
- width: 140px;
- height: 140px;
- filter: drop-shadow(0 0 30px rgba(6, 182, 212, 0.4));
- animation: logo-breathe 4s ease-in-out infinite;
}
-@keyframes logo-breathe {
- 0%, 100% {
- transform: scale(1);
- filter: drop-shadow(0 0 30px rgba(6, 182, 212, 0.4));
- }
- 50% {
- transform: scale(1.05);
- filter: drop-shadow(0 0 50px rgba(6, 182, 212, 0.6));
- }
+.cube {
+ width: 100%;
+ height: 100%;
+ position: relative;
+ transform-style: preserve-3d;
+ cursor: pointer;
+}
+
+.cube-face {
+ position: absolute;
+ width: 200px;
+ height: 200px;
+ background: #ffffff;
+ border: 2px solid rgba(6, 182, 212, 0.6);
+ box-shadow:
+ inset 0 0 30px rgba(0, 0, 0, 0.03),
+ 0 0 15px rgba(6, 182, 212, 0.3),
+ 0 0 30px rgba(6, 182, 212, 0.15);
+ user-select: none;
+}
+
+/* 立方体六个面 */
+.cube-face-front { transform: rotateY(0deg) translateZ(100px); }
+.cube-face-back { transform: rotateY(180deg) translateZ(100px); }
+.cube-face-right { transform: rotateY(90deg) translateZ(100px); }
+.cube-face-left { transform: rotateY(-90deg) translateZ(100px); }
+.cube-face-top { transform: rotateX(90deg) translateZ(100px); }
+.cube-face-bottom { transform: rotateX(-90deg) translateZ(100px); }
+
+/* 特性对话框 */
+.cube-tooltip {
+ position: absolute;
+ left: 50%;
+ top: 50%;
+ transform: translate(-50%, -50%) scale(0.8);
+ background: rgba(3, 7, 18, 0.95);
+ border: 1px solid rgba(6, 182, 212, 0.4);
+ border-radius: 12px;
+ padding: 16px 24px;
+ min-width: 220px;
+ max-width: 280px;
+ text-align: center;
+ opacity: 0;
+ pointer-events: none;
+ transition: opacity 0.3s ease, transform 0.3s ease;
+ z-index: 10;
+ backdrop-filter: blur(10px);
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4), 0 0 20px rgba(6, 182, 212, 0.15);
+}
+
+.cube-tooltip.is-visible {
+ opacity: 1;
+ transform: translate(-50%, -50%) scale(1);
+}
+
+.cube-tooltip-icon {
+ font-size: 28px;
+ margin-bottom: 8px;
+}
+
+.cube-tooltip-title {
+ font-size: 15px;
+ font-weight: 700;
+ color: #fff;
+ margin-bottom: 4px;
+}
+
+.cube-tooltip-desc {
+ font-size: 12px;
+ color: var(--text-muted);
+ line-height: 1.5;
+}
+
+/* 小三角箭头 */
+.cube-tooltip::after {
+ content: '';
+ position: absolute;
+ bottom: -8px;
+ left: 50%;
+ transform: translateX(-50%);
+ width: 0;
+ height: 0;
+ border-left: 8px solid transparent;
+ border-right: 8px solid transparent;
+ border-top: 8px solid rgba(6, 182, 212, 0.4);
}
/* 滚动指示器 */
@@ -277,10 +353,21 @@
width: 280px;
height: 280px;
}
- .hero-logo {
- width: 120px;
- height: 120px;
+ .cube-scene {
+ width: 160px;
+ height: 160px;
+ margin: 0 auto;
}
+ .cube-face {
+ width: 160px;
+ height: 160px;
+ }
+ .cube-face-front { transform: rotateY(0deg) translateZ(80px); }
+ .cube-face-back { transform: rotateY(180deg) translateZ(80px); }
+ .cube-face-right { transform: rotateY(90deg) translateZ(80px); }
+ .cube-face-left { transform: rotateY(-90deg) translateZ(80px); }
+ .cube-face-top { transform: rotateX(90deg) translateZ(80px); }
+ .cube-face-bottom { transform: rotateX(-90deg) translateZ(80px); }
}
@media (max-width: 640px) {
@@ -289,8 +376,19 @@
width: 240px;
height: 240px;
}
- .hero-logo {
- width: 100px;
- height: 100px;
+ .cube-scene {
+ width: 140px;
+ height: 140px;
+ margin: 0 auto;
}
+ .cube-face {
+ width: 140px;
+ height: 140px;
+ }
+ .cube-face-front { transform: rotateY(0deg) translateZ(70px); }
+ .cube-face-back { transform: rotateY(180deg) translateZ(70px); }
+ .cube-face-right { transform: rotateY(90deg) translateZ(70px); }
+ .cube-face-left { transform: rotateY(-90deg) translateZ(70px); }
+ .cube-face-top { transform: rotateX(90deg) translateZ(70px); }
+ .cube-face-bottom { transform: rotateX(-90deg) translateZ(70px); }
}
diff --git a/website/docs/architecture.html b/website/docs/architecture.html
new file mode 100644
index 0000000..51b9674
--- /dev/null
+++ b/website/docs/architecture.html
@@ -0,0 +1,105 @@
+
+
+
+
+
+ 架构设计 - Future OSS 文档
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 🏗️ 架构设计
+
+ 三层架构
+ 核心层 (oss/) — 插件管理、事件总线、消息总线、配置系统、日志系统。框架的核心基础设施。
+ 插件层 (store/) — 协议插件(HTTP/WS/TCP)、工具插件(依赖解析、存储、桥接)、中间件插件(熔断、热重载、生命周期)。
+ 应用层 (data/) — 第三方插件(HTML 渲染、Web 工具包)+ 运行时数据(配置文件、共享存储)。
+
+ 启动流程
+
+ - 加载
config.yaml → Config 对象
+ - 初始化 Logger
+ - 创建 PluginManager,只加载
plugin-loader
+ plugin-loader 扫描 store/ 目录,加载所有插件
+ - 使用
dependency 插件进行拓扑排序
+ - 按拓扑顺序 init() → start() 所有插件
+ - HTTP 服务器启动,注册路由
+ - 信号监听 → Ctrl+C 时优雅关闭(逆序 stop)
+
+
+ 目录结构
+ FutureOSS/
+├── oss/ # 核心框架
+│ ├── cli.py # CLI 入口
+│ ├── config/ # 配置加载
+│ ├── logger/ # 日志系统
+│ ├── plugin/ # 插件核心
+│ │ ├── types.py # 类型定义
+│ │ ├── loader.py # 动态加载器
+│ │ ├── manager.py # 插件管理器
+│ │ └── event_bus.py # 事件总线
+│ └── server/ # HTTP 服务器
+├── store/ # 本地插件仓库
+│ └── @{FutureOSS}/ # 官方插件
+└── data/ # 运行时数据
+
+
+
+
+
+
+
+ 获取更多信息
+
+
+
+
+
+
+
+
+
+
diff --git a/website/docs/development.html b/website/docs/development.html
new file mode 100644
index 0000000..2cbcf1d
--- /dev/null
+++ b/website/docs/development.html
@@ -0,0 +1,124 @@
+
+
+
+
+
+ 插件开发指南 - Future OSS 文档
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 🛠️ 插件开发指南
+
+ 插件结构
+ store/@{作者}/插件名/
+├── main.py # 插件入口(必须实现 Plugin 接口)
+└── manifest.json # 插件元数据(名称、版本、依赖)
+
+ 插件接口
+ from oss.plugin.types import Plugin
+
+class MyPlugin(Plugin):
+ def init(self, deps: dict = None):
+ # 初始化逻辑
+ pass
+
+ def start(self):
+ # 启动逻辑
+ pass
+
+ def stop(self):
+ # 停止逻辑
+ pass
+
+ @property
+ def manifest(self):
+ return {
+ "name": "my-plugin",
+ "version": "1.0.0",
+ "dependencies": [],
+ "description": "我的插件"
+ }
+
+ 关键原则
+
+ - 插件通过
from oss.plugin.types import Plugin 使用框架定义的接口
+ - 插件的
main.py 被 importlib 加载到框架的 Python 进程中
+ - 插件可以直接
from oss.xxx import xxx 引用框架模块
+ - 所有插件通过
config.json 配置,不修改源码
+
+
+ 依赖声明
+ // manifest.json
+{
+ "name": "html-render",
+ "version": "1.0.0",
+ "dependencies": ["http-api", "plugin-storage"],
+ "description": "HTML 渲染插件"
+}
+
+ 框架会自动调用 set_http_api() 和 set_plugin_storage() 注入依赖实例。
+
+ 安装格式
+ 格式为 @{作者名称}/插件名称,例如 @{Falck}/html-render。
+
+
+
+
+
+
+
+ 获取更多信息
+
+
+
+
+
+
+
+
+
+
diff --git a/website/docs/index.html b/website/docs/index.html
new file mode 100644
index 0000000..87672cd
--- /dev/null
+++ b/website/docs/index.html
@@ -0,0 +1,108 @@
+
+
+
+
+
+ 什么是 FutureOSS - Future OSS 文档
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 🧩 什么是 FutureOSS?
+
+ FutureOSS 是一个一切皆为插件的开发者工具运行时框架。框架本身是空壳,所有功能均以插件形式加载。
+
+ 项目定位
+ 协议、中间件、通知渠道……所有功能均以插件形式加载。内置熔断降级、依赖自动解析、事件驱动等企业级稳定性机制。
+
+ 核心特性
+
+ - 一切皆插件 — 框架本身不提供任何业务功能,所有能力通过插件扩展
+ - 热插拔 — 插件运行时加载与卸载,改完即生效,零编译
+ - 依赖自动解析 — 拓扑排序 (Kahn 算法) + 循环依赖检测
+ - 熔断与降级 — 自动熔断,支持 closed/open/half-open 状态切换
+ - 包管理系统 — 一键安装/卸载/更新插件,支持
@{作者}/插件名 格式
+ - 事件驱动 — 发布/订阅 + 通配符匹配 + RPC 桥接
+ - 统一存储 — plugin-storage 为每个插件提供隔离的文件读写入口
+
+
+
+
+ 关键原则
+
+ 类型共享
+ 框架在 oss/plugin/types.py 中定义所有数据类型和接口,插件通过 from oss.plugin.types import Plugin 直接使用。插件不应重复定义 Logger、EventBus 等类型。
+
+ 配置驱动
+ 所有插件通过 config.json 配置,不修改源码。配置文件使用相对路径,相对于 config.json 所在目录。
+
+ 插件安装格式
+ 格式为 @{作者名称}/插件名称,命令:oss pkg install @{Falck}/http-server
+
+
+
+
+
+
+
+ 获取更多信息
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/website/docs/plugins.html b/website/docs/plugins.html
new file mode 100644
index 0000000..b27f2cd
--- /dev/null
+++ b/website/docs/plugins.html
@@ -0,0 +1,90 @@
+
+
+
+
+
+ 官方插件列表 - Future OSS 文档
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 📦 官方插件列表
+
+
+ | 插件名 | 说明 | 依赖 |
+
+ plugin-loader | 核心插件,扫描/加载/管理所有插件 | 无 |
+ dependency | 拓扑排序 (Kahn 算法) + 循环依赖检测 | 无 |
+ http-api | HTTP 服务器 (8080) + 路由 + 中间件 + CORS | 无 |
+ http-tcp | HTTP TCP 服务器 (8082) | 无 |
+ ws-api | WebSocket 服务器 (8081) + 事件总线 | 无 |
+ plugin-storage | 统一文件读写 + JSON 键值存储 + 目录隔离 | 无 |
+ plugin-bridge | 事件总线 + 广播 + RPC + 桥接 | plugin-storage |
+ circuit-breaker | 熔断器 (closed/open/half-open) | 无 |
+ hot-reload | 文件监听 + 热加载/卸载/更新插件 | 无 |
+ lifecycle | 生命周期状态机 (pending/running/stopped) | 无 |
+ json-codec | JSON 序列化/反序列化 + Schema 验证 | 无 |
+ pkg | 包管理 (搜索/安装/卸载/更新) | 无 |
+
+
+
+
+
+
+
+
+
+ 获取更多信息
+
+
+
+
+
+
+
+
+
+
diff --git a/website/docs/quickstart.html b/website/docs/quickstart.html
new file mode 100644
index 0000000..41ef04f
--- /dev/null
+++ b/website/docs/quickstart.html
@@ -0,0 +1,106 @@
+
+
+
+
+
+ 快速开始 - Future OSS 文档
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 🚀 三步运行
+
+ 步骤 1:克隆代码
+ git clone https://gitee.com/starlight-apk/feature-oss.git
+cd feature-oss
+
+ 步骤 2:安装依赖
+ pip install -r requirements.txt
+pip install -e .
+
+ 步骤 3:启动服务
+ bash start.sh
+# 或 Windows: start.bat
+
+ 启动后访问 http://localhost:8080/ 即可看到网站。
+
+ 系统要求
+
+ - Python 3.8+
+ - Linux / macOS / Windows
+ - 核心依赖:click、pyyaml、websockets
+
+
+ 常用命令
+
+ | 命令 | 说明 |
+
+ oss serve | 启动框架服务 |
+ oss init | 初始化项目配置 |
+ oss version | 查看版本号 |
+ oss status | 查看插件运行状态 |
+ oss pkg install @{作者}/插件名 | 安装远程插件 |
+ oss pkg list | 列出已安装插件 |
+
+
+
+
+
+
+
+
+
+ 获取更多信息
+
+
+
+
+
+
+
+
+
+
diff --git a/website/docs/why-python.html b/website/docs/why-python.html
new file mode 100644
index 0000000..cce6a4e
--- /dev/null
+++ b/website/docs/why-python.html
@@ -0,0 +1,98 @@
+
+
+
+
+
+ 为什么选择 Python - Future OSS 文档
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 🐍 为什么从 Go 重构为 Python?
+
+ Go 的 plugin 包不适合热插拔场景。.so 文件与主程序是独立编译单元,类型不共享,依赖注入后接口不匹配会导致 panic。Python 的动态特性天然适合插件化架构。
+
+ 技术对比
+
+
+ | 问题 | Go 方案 | Python 方案 |
+
+
+ | 插件热插拔 | plugin.Open(".so") | importlib 动态加载 .py |
+ | 依赖注入 | 反射注入,类型不匹配 → panic | 直接传 dict/对象,无编译隔离 |
+ | 开发效率 | 每次改插件需重新编译 | 改完即生效,零编译 |
+ | 配置类型 | map[string]string 限制 | dict[str, Any] 原生支持任意类型 |
+
+
+
+ Go 插件系统的致命问题
+ Go 的插件机制依赖 plugin.Open() 加载编译好的 .so 文件。每个 .so 是独立的编译单元,无法共享类型定义。这意味着插件中定义的接口与框架中的接口即使签名相同,也被视为不同类型,导致依赖注入后接口为 nil,运行时直接 panic。
+
+ Python 的优势
+
+ - 动态类型 — 没有编译时类型检查,插件直接使用框架定义的类型
+ - importlib — 运行时动态加载
.py 文件,零编译开销
+ - 类型共享 — 插件通过
from oss.plugin.types import Plugin 直接引用框架类型
+ - 开发迭代快 — 改完代码即生效,无需重新编译
+
+
+
+
+
+
+
+
+ 获取更多信息
+
+
+
+
+
+
+
+
+
+
diff --git a/website/index.html b/website/index.html
index 2304a97..a9f2696 100644
--- a/website/index.html
+++ b/website/index.html
@@ -24,9 +24,9 @@
-
+
-
+
2026 · 插件驱动 · 一切皆可扩展
@@ -59,7 +59,21 @@
-

+
@@ -71,5 +85,6 @@
+