diff --git a/wwwroot/workbench/workbench.html b/wwwroot/workbench/workbench.html
new file mode 100644
index 0000000..54a1b1a
--- /dev/null
+++ b/wwwroot/workbench/workbench.html
@@ -0,0 +1,64 @@
+
+
+
+
+元景 · 游戏工作台
+
+
+
+
+
+
+
对象树(世界 1 · 场景 N · 实体 N)
+
加载中…
+
+
+
+ 未选择对象
+
+
+
+
+
+
+
+
+
+
+
diff --git a/wwwroot/workbench/workbench.js b/wwwroot/workbench/workbench.js
new file mode 100644
index 0000000..3cf8314
--- /dev/null
+++ b/wwwroot/workbench/workbench.js
@@ -0,0 +1,143 @@
+/* 元景游戏工作台:game 聚合根单页编辑器 */
+(function () {
+ function api(path, params) {
+ return fetch(path, {
+ method: 'POST',
+ headers: {'Content-Type': 'application/json'},
+ body: JSON.stringify(params || {})
+ }).then(function (r) { return r.json(); });
+ }
+ function base() { return '/scense_game'; }
+
+ var state = { game: null, data: null, sel: null }; // sel: {type, id, name}
+
+ function msg(t, ok) {
+ var el = document.getElementById('msg');
+ el.textContent = t;
+ el.className = ok ? 'ok' : 'err';
+ }
+
+ function saveGame() {
+ var name = document.getElementById('game_name').value.trim();
+ if (state.game) { msg('游戏已存在: ' + state.game.id, true); return; }
+ if (!name) { msg('先填游戏名称', false); return; }
+ api(base() + '/game/api/game_create.dspy', {name: name,
+ description: document.getElementById('game_shared').checked ? 'shared' : 'independent'})
+ .then(function (r) {
+ if (r.success) { msg('游戏创建成功,世界已自动建立', true); reload(); }
+ else msg(r.message || '创建失败', false);
+ });
+ }
+
+ function reload() {
+ // 列表取第一个 game 或新建后带入
+ api(base() + '/game/api/game_list.dspy', {}).then(function (r) {
+ var games = (r.data && r.data.games) || [];
+ if (!games.length) { state.game = null; renderTree(null); return; }
+ var gid = games[0].game_id || games[0].id;
+ api(base() + '/game/api/game_workbench.dspy', {game_id: gid}).then(function (w) {
+ if (!w.success) { msg(w.message, false); return; }
+ state.game = w.data.game; state.data = w.data;
+ document.getElementById('game_name').value = (w.data.game && w.data.game.name) || '';
+ renderTree(w.data);
+ if (!state.sel) selectWorld();
+ else loadSel();
+ });
+ });
+ }
+
+ function renderTree(d) {
+ var el = document.getElementById('tree_body');
+ if (!d || !d.world) { el.innerHTML = '尚无游戏,先填名称保存
'; return; }
+ var h = '';
+ h += '🌍 ' + esc(d.world.name) + '
';
+ (d.scenes || []).forEach(function (s) {
+ h += '🎬 ' + esc(s.name) + '
';
+ });
+ h += '+ 场景
';
+ (d.entities || []).forEach(function (e) {
+ h += '📦 ' + esc(e.name) + (e.scene_id ? '' : '(世界级)') + '
';
+ });
+ h += '+ 实体
';
+ el.innerHTML = h;
+ }
+ function esc(s) { return String(s || '').replace(/'/g, "\\'").replace(/