- /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 期)
144 lines
5.4 KiB
HTML
144 lines
5.4 KiB
HTML
<!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>
|