diff --git a/README.md b/README.md
index 0139a90..f14ddd3 100644
--- a/README.md
+++ b/README.md
@@ -17,6 +17,8 @@
- **基础动作**:角色内置走路 / 跑步循环动作(真实步态曲线、左右对侧摆臂、跑步独立步频与屈膝曲线),支持速度 / 幅度调节与群体相位错开;动作之上可按关节叠加姿势偏移微调
- **姿势调节**:两级折叠分组(核心 / 左右臂 / 左右腿),20 种姿势预设一键应用
- **视频导出**:上帝视角或机位视角,WebCodecs 逐帧快速导出 MP4(固定分辨率、不随视口布局变形,导出速度远快于实时)
+- **多工程管理**:顶栏左侧「工程」菜单可新建 / 切换 / 重命名 / 复制 / 删除工程,每个工程独立保存场景与关键帧
+- **工程文件**:一键把工程保存为 `.json` 文件(模型二进制内联,文件自包含),也可从文件导入为新工程
- 本地场景与关键帧状态持久化
## 界面截图
@@ -48,7 +50,7 @@ src
├─ editor/canvas # Three.js / R3F 视口、画幅框、工具条、截图视图、回放覆盖
├─ editor/panels # 左侧对象树、右侧属性面板、底部时间轴
├─ editor/store # Zustand 状态管理、撤销、剪贴板、关键帧 actions
-├─ editor/io # 截图导出、视频导出、工程导入导出、宿主通信
+├─ editor/io # 截图导出、视频导出、多工程目录、工程文件读写、宿主通信
├─ editor/loaders # 本地模型与全景图导入
├─ editor/runtime # 角色渲染、骨骼、姿势应用、播放状态与回放驱动
├─ editor/schema # 数据结构、机位、视口、时间轴与插值定义
@@ -111,6 +113,10 @@ http://127.0.0.1:4173/
## 常用操作
- 顶部可切换 `导演视角` 与 `机位视角`
+- **顶栏左侧「工程」菜单**:
+ - 点工程名切换工程(每个工程的场景、机位、关键帧互相独立)
+ - 每行右侧:重命名 / 复制工程 / 保存到文件 / 删除(删除需二次确认,且至少保留一个工程)
+ - 底部:`新建工程`(空场景)、`导入工程文件`(把外部 `.json` 导入为新的工程并切换过去)
- 左侧用于搜索、选择、分组查看场景对象,并支持可见性 / 锁定 / 删除
- 中央视口用于摆放场景、切换变换模式、添加角色和机位、导入资源与截图
- 右侧属性面板会根据当前选中对象自动切换为场景 / 角色 / 模型 / 摄像机编辑面板;选中摄像机时可直接编辑 位置 / 注视坐标 / FOV
@@ -142,10 +148,12 @@ http://127.0.0.1:4173/
## 数据与嵌入
- 当前场景、本地模型库与关键帧都会写入浏览器 `localStorage`
+- **多工程存储**:工程目录存在 `storyai-3d-director-project-catalog`(工程列表 + 当前激活工程),每个工程的场景写在 `storyai-3d-director-desk-demo:<工程 id>` 这个独立槽位上;切工程 = 换槽位,互不干扰
+- **首次升级**:老版本把场景写在基础 key `storyai-3d-director-desk-demo` 上,首次启动会自动把它搬迁成第一个「默认工程」(复制而非删除,旧 key 保留)
- 工程数据为 `version: 2`,含 `timeline` 字段(物体轨道 `tracks` + 相机运镜轨道 `cameraTracks`);导入旧 v1 工程会自动迁移、补齐空时间轴
-- 支持导出工程 JSON,也支持通过文件重新导入
+- **工程文件**(`storyai-director-project` 信封格式):保存时会把 IndexedDB 里的 GLB/GLTF 内联为 data URL,使文件自包含;导入时会再把模型落回 IndexedDB,保持 localStorage 轻量。同时兼容早期直接导出的裸工程 JSON
- 支持“保存最近工程 / 恢复最近工程”
-- 组件已包含宿主页面通信桥,适合嵌入到更大的创作工作台中
+- 组件已包含宿主页面通信桥,适合嵌入到更大的创作工作台中(宿主若通过 `?instanceId=` 指定实例作用域,该作用域优先于多工程的当前工程)
## Electron 桌面版打包
@@ -189,7 +197,7 @@ pnpm test
最近一次核对结果(pnpm 迁移后):
- `pnpm run build` 可通过(`tsc -b` 类型检查 + Vite 生产构建)
-- `pnpm test`:**40 个测试文件全部通过,395 通过 / 3 跳过 / 0 失败**
+- `pnpm test`:**58 个测试文件全部通过,725 通过 / 3 跳过 / 0 失败**
- 构建阶段会出现 Vite 警告:模型库缩略图 URL 在构建期不存在(`模型库/` 是仓库外的外部资源目录),会保留到运行时解析;同时主包体积超过默认 chunk 警告阈值。两者都不影响构建结果
> 模型库说明:内置模型库读取的是项目**上一级**的 `模型库/` 目录(`import.meta.glob("../../../../模型库/**/*.fbx")`)。仓库不含该目录,因此模型库面板在纯净检出下为空——glob 匹配为空不会报错,属于预期行为。相关测试在目录缺失时会自动跳过。
diff --git a/electron/main.cjs b/electron/main.cjs
index 100bde1..b9ddb00 100644
--- a/electron/main.cjs
+++ b/electron/main.cjs
@@ -4,7 +4,7 @@ const path = require('path');
// 与 package.json 的 build.appId 保持一致:
// Windows 靠 AppUserModelID 做任务栏图标归组与通知身份识别,不设置会出现"图标分身"。
if (process.platform === 'win32') {
- app.setAppUserModelId('com.storyai.director-desk');
+ app.setAppUserModelId('com.ttstd.director-desk');
}
Menu.setApplicationMenu(null);
diff --git a/package.json b/package.json
index 031b00e..a850712 100644
--- a/package.json
+++ b/package.json
@@ -26,7 +26,7 @@
"icon": "python scripts/generate_icon.py"
},
"build": {
- "appId": "com.storyai.director-desk",
+ "appId": "com.ttstd.director-desk",
"productName": "故事AI导演工作台",
"directories": {
"output": "release"
diff --git a/src/App.tsx b/src/App.tsx
index 5a1a471..3ec058b 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -3,6 +3,7 @@ import { useEffect } from "react";
import { DirectorDeskShell } from "./app/layout/DirectorDeskShell";
import { DirectorCanvas } from "./editor/canvas/DirectorCanvas";
import { initDirectorDeskHostBridge } from "./editor/io/hostBridge";
+import { ProjectManagerMenu } from "./editor/panels/ProjectManagerMenu";
import { addKeyframeAtPlayhead } from "./editor/runtime/keyframeCommand";
import { useDirectorStore } from "./editor/store/directorStore";
@@ -100,9 +101,11 @@ export default function App() {
return (
- {/* 占位:顶栏是「左栏宽 / 中间 1fr / 右栏宽」三列栅格,
- 少了这块,中间的视角切换会落到左列里去,左对齐而不是居中。 */}
-
+ {/* 顶栏是「左栏宽 / 中间 1fr / 右栏宽」三列栅格:左侧放工程管理入口,
+ 中间保持视角切换居中(少了左列,视角切换会落到左列去而左对齐)。 */}
+