Files
story-edit-web/web
邓雨鹏 676df30c67 @
feat(web): 演出配置 Timeline 加「场景底图」选择器(venue 特写)

- 后端 /api/sceneshots:列 SceneShots 全部俯视底图(venue 特写) name->{url,bounds}
- timeline.js:底图优先级 ir.stage.backdrop(venue) > 点位集默认 shot;
  顶栏加底图下拉 renderMapInfo + applyBackdrop(换底+改投影范围+重画+回调)
- app.js:拉 /api/sceneshots;performSelect 传入;saveBackdrop 写 ir.stage.backdrop 并 PUT
- venue 特写与点位集同 map-local → 换底图后锚点自动落对位(无头实拍擂台验证)
- ir.stage.backdrop 是编辑器元数据:validate 不读、compile 不碰
@
2026-06-15 12:01:14 +08:00
..
@
2026-06-15 12:01:14 +08:00
@
2026-06-15 12:01:14 +08:00

Story 事件协作 Web 编辑器M5

设计:docs/plans/2026-06-06-story-event-pipeline-design.md§5.1/§6, D1D4/D8 计划:docs/plans/2026-06-08-story-event-M5-web-editor-plan.md

少数人各凭专属口令(口令即身份,改动自动署名)在网页里审校/编辑剧情事件 → 静态校验 + 剧本试走(零引擎)→ 一键编译 所有 confirmed 事件成 .events.json + .i18n.tsv 打包下载。校验/编译走 ir_core,与 CLI ir_compile.py)逐字节同口径。

起服务

cd tools/event_authoring/web
pip install -r requirements.txt
# Windows PowerShell: $env:STORY_WEB_USERS="bia:口令A,ljl:口令B"
set STORY_WEB_USERS=bia:口令A,ljl:口令B   # 必填;未配置则拒绝启动
uvicorn app:app --host 0.0.0.0 --port 8787

浏览器打开 http://<host>:8787,输入自己的专属口令进入(服务端按口令认人, updated_by 自动署名;口令要求 ≥8 位且互不相同cookie 只存随机会话 token 不存口令; 从 STORY_WEB_USERS 移除某人即吊销其所有会话)。

用法

  1. 导入 IR:右上「导入 IR」粘贴单个或数组形式的 IR JSONsamples/*.ir.json)。
  2. 审校/编辑:左栏选事件 → 中栏分支树 → 点节点在右栏改文案/增删节点/下拉改分支/角色表/点位下拉。
  3. 校验:与 CLI 同口径(断链、选项无兜底、未登记 kind、未声明角色、点位缺失、out_ref 失效…)。
  4. 试走:从首节点走,点选项/掷随机/手选战斗胜负,实时累计银两/道具/友好度账面与结局。
  5. 确认/丢弃改事件状态pending/confirmed/discarded
  6. 导出 confirmed:编译所有 confirmed → story_export.zip;任一 confirmed 校验不过则整体拒绝。

导出后把 {group}.events.json 放进 Assets/StreamingAssets/Story/Config/(或 Qiyu/ 子目录), {group}.i18n.tsv 的韩文翻译合并进 Assets/StreamingAssets/i18n/ko.tsv

数据

  • 事件存 SQLite story_events.db(本目录,已 gitignore末次写入生效不做锁
  • 词典 ../ir_dictionary.json、点位集 Assets/StreamingAssets/Story/PointSets/*.points.json 只读引用。

Docker 部署M6

单容器FastAPI + 静态前端 + SQLite + 纯 Python 编译器)。构建上下文是 tools/event_authoring(需含 ir_core/ir_dictionary.json/web)。

cd tools/event_authoring/web
STORY_WEB_USERS="bia:口令A,ljl:口令B" docker compose up -d --build
# 或不用 compose
#   docker build -f web/Dockerfile -t story-event-web ..
#   docker run -d -p 8787:8787 -e STORY_WEB_USERS="bia:口令A,ljl:口令B" \
#     -v "$PWD/web/data:/data" \
#     -v "$PWD/Assets/StreamingAssets/Story/PointSets:/pointsets:ro" story-event-web
  • ./data:/dataSQLite 持久化,容器重建不丢事件,勿删 …/PointSets:/pointsets:ro(开发侧点位集只读;缺失时坐标校验降级为警告)。
  • 环境变量STORY_WEB_USERS(必填,名字1:口令1,名字2:口令2,未配置拒绝启动)、 STORY_WEB_PORT(宿主端口,默认 8787STORY_DB_PATH(默认 /data/story_events.db)、STORY_POINTSETS_DIR(默认 /pointsets)、 可选 TZ=Asia/Shanghai(否则 updated_at 按 UTC 显示)。
  • NAS + VPSNAS 跑容器VPS 用反代/frp/Cloudflare Tunnel 把 8787 映射出去。点位集更新只需 同步文件到 NAS 的 /pointsets 卷路径,无需重建镜像。备份=拷 data/story_events.db

API鉴权后

POST /api/login · GET /api/dictionary · GET /api/pointsets · POST /api/import · GET /api/events?status= · GET /api/events/{group} · PUT /api/events/{group} · POST /api/events/{group}/status · POST /api/validate · POST /api/export

非目标(见设计)

容器化部署M6、多人账号/并发锁、手拖画布、引擎侧新语义、把坐标嵌进 events.json。