Files
story-edit-web/web/static/index.html
邓雨鹏 dbf857769e feat(timeline): P1 白模演出预览——时间线+俯视舞台播放
- /api/pointsets 增 anchors(含 pos/rot/kind/npc 坐标),保留 points 名字数组兼容下拉
- 新增 static/timeline.js:线性化主路径→按时长铺多轨时间线 + 2D 俯视白模舞台播放
  (走位插值/对话打字机/镜头俯视框示意/playhead/点击跳转);战斗/选择/随机仅标点不模拟
- 工具栏加「演出预览」按钮 + 预览遮罩 + 暗金主题样式
- 时长模型:对话=字数×打字机速度,走位=坐标距离÷速度,动画/镜头给缺省时长
- node 离线测试两样张(含 out_ref+fight+skip)逻辑全过;修掉结局重复渲染 bug

设计文档见主仓 docs/plans/2026-06-13-story-timeline-editor-and-whitebox-preview-design.md (P1 期)
2026-06-13 10:52:20 +08:00

144 lines
5.4 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Story 协作编辑器 · M5</title>
<link rel="stylesheet" href="vendor/drawflow.min.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<!-- 登录遮罩 -->
<div id="login" class="overlay">
<div class="login-box">
<h2>剧情事件协作编辑器</h2>
<p class="hint">输入你的专属口令进入(口令即身份,改动记录自动署名)</p>
<input id="login-pass" type="password" placeholder="专属口令" autocomplete="off">
<button id="login-btn">进入</button>
<div id="login-err" class="err"></div>
</div>
</div>
<header>
<h1>剧情事件协作编辑器 <span class="ver">M5</span></h1>
<div class="toolbar">
<button id="btn-save" class="primary" disabled>保存</button>
<button id="btn-validate" disabled>校验</button>
<button id="btn-playtest" disabled>试走</button>
<button id="btn-timeline" disabled>演出预览</button>
<span class="sep"></span>
<button id="btn-confirm" disabled>确认</button>
<button id="btn-discard" disabled>丢弃</button>
<span class="sep"></span>
<button id="btn-import">导入 IR</button>
<button id="btn-export">导出 confirmed</button>
<span class="who" id="who"></span>
</div>
</header>
<div id="wrap">
<!-- 左:事件列表 -->
<aside id="list-pane">
<div class="filters">
<select id="filter-status">
<option value="all">全部</option>
<option value="pending">待审</option>
<option value="confirmed">已确认</option>
<option value="discarded">已丢弃</option>
</select>
<input id="search" type="text" placeholder="搜索标题/group">
</div>
<div id="event-list"></div>
</aside>
<!--分支图Drawflow 可拖拽连线) -->
<main id="graph-pane">
<div id="graph-tools">
<button id="btn-undo" class="mini" disabled title="撤销 (Ctrl+Z)">↶ 撤销</button>
<button id="btn-redo" class="mini" disabled title="重做 (Ctrl+Y)">↷ 重做</button>
<span class="gsep"></span>
<button id="btn-autolayout" class="mini" disabled title="自动整理布局 (R)">自动整理</button>
<button id="btn-addsucc" class="mini" disabled title="给选中节点加后继 (Enter)">加后继</button>
<span class="tip">拖出口圆点→目标=连跳转 · 拖动摆位 · Del 删除 · R 整理 · Enter 加后继 · Ctrl+Z/Y 撤销重做</span>
</div>
<div id="drawflow"></div>
<div id="graph-empty" class="empty-center">从左侧选择一个事件</div>
</main>
<!-- 右:表单编辑 -->
<section id="edit-pane">
<div id="meta-edit"></div>
<div class="sec-title">节点编辑 <button id="btn-addnode" class="mini" disabled>+节点</button></div>
<div id="node-edit"><div class="empty">点击中间任意节点进行编辑</div></div>
</section>
</div>
<!-- 校验结果遮罩 -->
<div id="validate-modal" class="overlay hidden">
<div class="modal">
<h3>校验结果</h3>
<div id="validate-body"></div>
<button class="modal-close">关闭</button>
</div>
</div>
<!-- 导入遮罩 -->
<div id="import-modal" class="overlay hidden">
<div class="modal">
<h3>导入 IR选择一个或多个 JSON 文件)</h3>
<div id="import-drop" class="drop">
<p>点击选择文件,或把 .json 文件拖到这里</p>
<p class="hint">每个文件可为单个事件对象,或事件数组;支持多选</p>
<input id="import-file" type="file" accept=".json,application/json" multiple hidden>
</div>
<div id="import-files" class="filelist"></div>
<details class="import-paste">
<summary>或粘贴 JSON 文本</summary>
<textarea id="import-text" placeholder='{"id":"QY_XXX", ...} 或 [ {...}, {...} ]'></textarea>
</details>
<div class="modal-actions">
<button id="import-do" class="primary">导入</button>
<button class="modal-close">取消</button>
</div>
<div id="import-result" class="err"></div>
</div>
</div>
<!-- 试走遮罩 -->
<div id="playtest-modal" class="overlay hidden">
<div class="modal wide">
<h3>剧本试走 <button class="modal-close" style="float:right">关闭</button></h3>
<div id="pt-layout">
<div id="pt-flow"></div>
<div id="pt-ledger"></div>
</div>
</div>
</div>
<!-- 演出预览遮罩:上=俯视白模舞台,下=时间线+playhead -->
<div id="tl-modal" class="overlay hidden">
<div class="modal huge">
<h3>演出预览(白模)<span id="tl-mapinfo" class="tl-mapinfo"></span><button class="modal-close" style="float:right">关闭</button></h3>
<div id="tl-stagewrap">
<canvas id="tl-stage" width="780" height="380"></canvas>
</div>
<div id="tl-controls">
<button id="tl-play" class="primary">▶ 播放</button>
<button id="tl-restart" class="mini">⏮ 重头</button>
<span id="tl-time" class="tl-time">0.0 / 0.0s</span>
<span class="tip">点时间轴任意处跳转 · 战斗/选择/随机仅标点不模拟 · 预览沿首出口主路径</span>
</div>
<div id="tl-tracks"></div>
</div>
</div>
<script src="vendor/drawflow.min.js"></script>
<script src="graph.js"></script>
<script src="form.js"></script>
<script src="playtest.js"></script>
<script src="timeline.js"></script>
<script src="app.js"></script>
</body>
</html>